From c2dbfc1d6ca677f9b6fb8eaa60e4003a903e26bd Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: MAC: Make gem5 compile and run on MacOSX 10.7.2 Adaptations to make gem5 compile and run on OSX 10.7.2, with a stock gcc 4.2.1 and the remaining dependencies from macports, i.e. python 2.7,.2 swig 2.0.4, mercurial 2.0. The changes include an adaptation of the SConstruct to handle non-library linker flags, and Darwin-specific code to find the memory usage of gem5. A number of Ruby files relied on ambigious uint (without the 32 suffix) which caused compilation errors. --- src/base/hostinfo.cc | 32 +++++++++++++++++++++- src/base/hostinfo.hh | 8 ++++-- src/cpu/testers/directedtest/DirectedGenerator.hh | 2 +- .../testers/directedtest/InvalidateGenerator.cc | 2 +- .../testers/directedtest/InvalidateGenerator.hh | 8 +++--- src/cpu/testers/directedtest/RubyDirectedTester.hh | 4 +-- .../testers/directedtest/SeriesRequestGenerator.cc | 2 +- .../testers/directedtest/SeriesRequestGenerator.hh | 6 ++-- 8 files changed, 49 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/base/hostinfo.cc b/src/base/hostinfo.cc index 5ff34e603..857ccfa7f 100644 --- a/src/base/hostinfo.cc +++ b/src/base/hostinfo.cc @@ -30,6 +30,12 @@ #include +#ifdef __APPLE__ +#include +#include +#include +#endif + #include #include #include @@ -82,7 +88,31 @@ procInfo(const char *filename, const char *target) } if (fp) - fclose(fp); + fclose(fp); return 0; } + +uint64_t +memUsage() +{ +// For the Mach-based Darwin kernel, use the task_info of the self task +#ifdef __APPLE__ + struct task_basic_info t_info; + mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; + + if (KERN_SUCCESS != task_info(mach_task_self(), + TASK_BASIC_INFO, (task_info_t)&t_info, + &t_info_count)) { + return 0; + } + + // Mimic Darwin's implementation of top and subtract + // SHARED_REGION_SIZE from the tasks virtual size to account for the + // shared memory submap that is incorporated into every process. + return (t_info.virtual_size - SHARED_REGION_SIZE) / 1024; +#else + // Linux implementation + return procInfo("/proc/self/status", "VmSize:"); +#endif +} diff --git a/src/base/hostinfo.hh b/src/base/hostinfo.hh index ac7d40f13..d9a30481a 100644 --- a/src/base/hostinfo.hh +++ b/src/base/hostinfo.hh @@ -39,7 +39,11 @@ std::string &hostname(); uint64_t procInfo(const char *filename, const char *target); -inline uint64_t memUsage() -{ return procInfo("/proc/self/status", "VmSize:"); } +/** + * Determine the simulator process' total virtual memory usage. + * + * @return virtual memory usage in kilobytes + */ +uint64_t memUsage(); #endif // __HOSTINFO_HH__ diff --git a/src/cpu/testers/directedtest/DirectedGenerator.hh b/src/cpu/testers/directedtest/DirectedGenerator.hh index 904dcf399..c156efff0 100644 --- a/src/cpu/testers/directedtest/DirectedGenerator.hh +++ b/src/cpu/testers/directedtest/DirectedGenerator.hh @@ -43,7 +43,7 @@ class DirectedGenerator : public SimObject virtual ~DirectedGenerator() {} virtual bool initiate() = 0; - virtual void performCallback(uint proc, Addr address) = 0; + virtual void performCallback(uint32_t proc, Addr address) = 0; void setDirectedTester(RubyDirectedTester* directed_tester); diff --git a/src/cpu/testers/directedtest/InvalidateGenerator.cc b/src/cpu/testers/directedtest/InvalidateGenerator.cc index 902c6cc15..4d8271a05 100644 --- a/src/cpu/testers/directedtest/InvalidateGenerator.cc +++ b/src/cpu/testers/directedtest/InvalidateGenerator.cc @@ -103,7 +103,7 @@ InvalidateGenerator::initiate() } void -InvalidateGenerator::performCallback(uint proc, Addr address) +InvalidateGenerator::performCallback(uint32_t proc, Addr address) { assert(m_address == address); diff --git a/src/cpu/testers/directedtest/InvalidateGenerator.hh b/src/cpu/testers/directedtest/InvalidateGenerator.hh index 14c47b70b..50db180e3 100644 --- a/src/cpu/testers/directedtest/InvalidateGenerator.hh +++ b/src/cpu/testers/directedtest/InvalidateGenerator.hh @@ -49,14 +49,14 @@ class InvalidateGenerator : public DirectedGenerator ~InvalidateGenerator(); bool initiate(); - void performCallback(uint proc, Addr address); + void performCallback(uint32_t proc, Addr address); private: InvalidateGeneratorStatus m_status; Addr m_address; - uint m_active_read_node; - uint m_active_inv_node; - uint m_addr_increment_size; + uint32_t m_active_read_node; + uint32_t m_active_inv_node; + uint32_t m_addr_increment_size; }; #endif //__CPU_DIRECTEDTEST_INVALIDATEGENERATOR_HH__ diff --git a/src/cpu/testers/directedtest/RubyDirectedTester.hh b/src/cpu/testers/directedtest/RubyDirectedTester.hh index 163c206d8..53c389692 100644 --- a/src/cpu/testers/directedtest/RubyDirectedTester.hh +++ b/src/cpu/testers/directedtest/RubyDirectedTester.hh @@ -53,11 +53,11 @@ class RubyDirectedTester : public MemObject RubyDirectedTester *tester; public: - CpuPort(const std::string &_name, RubyDirectedTester *_tester, uint _idx) + CpuPort(const std::string &_name, RubyDirectedTester *_tester, uint32_t _idx) : SimpleTimingPort(_name, _tester), tester(_tester), idx(_idx) {} - uint idx; + uint32_t idx; protected: virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/testers/directedtest/SeriesRequestGenerator.cc b/src/cpu/testers/directedtest/SeriesRequestGenerator.cc index 43e140178..4cf9aed1c 100644 --- a/src/cpu/testers/directedtest/SeriesRequestGenerator.cc +++ b/src/cpu/testers/directedtest/SeriesRequestGenerator.cc @@ -89,7 +89,7 @@ SeriesRequestGenerator::initiate() } void -SeriesRequestGenerator::performCallback(uint proc, Addr address) +SeriesRequestGenerator::performCallback(uint32_t proc, Addr address) { assert(m_active_node == proc); assert(m_address == address); diff --git a/src/cpu/testers/directedtest/SeriesRequestGenerator.hh b/src/cpu/testers/directedtest/SeriesRequestGenerator.hh index 97b632a12..9b1c3e8ba 100644 --- a/src/cpu/testers/directedtest/SeriesRequestGenerator.hh +++ b/src/cpu/testers/directedtest/SeriesRequestGenerator.hh @@ -49,13 +49,13 @@ class SeriesRequestGenerator : public DirectedGenerator ~SeriesRequestGenerator(); bool initiate(); - void performCallback(uint proc, Addr address); + void performCallback(uint32_t proc, Addr address); private: SeriesRequestGeneratorStatus m_status; Addr m_address; - uint m_active_node; - uint m_addr_increment_size; + uint32_t m_active_node; + uint32_t m_addr_increment_size; bool m_issue_writes; }; -- cgit v1.2.3 From 59b7cad3ec6ae02f53b53865b365101b1856bb93 Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: SWIG: Make gem5 compile and link with swig 2.0.4 To make gem5 compile and run with swig 2.0.4 a few minor fixes are necessary, the fail label issues by swig must not be treated as an error by gcc (tested with gcc 4.2.1), and the vector wrappers must have SWIGPY_SLICE_ARG defined which happens in pycontainer.swg, included through std_container.i. By adding the aforementioned include to the vector wrappers everything seems to work. --- src/SConscript | 2 +- src/python/m5/params.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 0a4bb57f4..7fb03e821 100755 --- a/src/SConscript +++ b/src/SConscript @@ -851,8 +851,8 @@ def makeEnv(label, objsfx, strip = False, **kwargs): swig_env.Append(CCFLAGS='-Wno-uninitialized') swig_env.Append(CCFLAGS='-Wno-sign-compare') swig_env.Append(CCFLAGS='-Wno-parentheses') + swig_env.Append(CCFLAGS='-Wno-unused-label') if compareVersions(env['GCC_VERSION'], '4.6.0') != -1: - swig_env.Append(CCFLAGS='-Wno-unused-label') swig_env.Append(CCFLAGS='-Wno-unused-but-set-variable') werror_env = new_env.Clone() diff --git a/src/python/m5/params.py b/src/python/m5/params.py index ee3678dc9..03917d085 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -256,6 +256,9 @@ class VectorParamDesc(ParamDesc): self.ptype.cxx_predecls(code) code('%}') code() + # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion + code('%include "std_container.i"') + code() self.ptype.swig_predecls(code) code() code('%include "std_vector.i"') -- cgit v1.2.3 From 3f9e352de4e1ac34e1f0b83c3f66af2175b524f4 Mon Sep 17 00:00:00 2001 From: Dam Sunwoo Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: Base: Fixed shift amount in genrand() to work with large numbers The previous version didn't work correctly with max integer values (2^31-1 for 32-bit, 2^63-1 for 64bit version), causing "shift" to become -1. For smaller numbers, it wouldn't have caused functional errors, but would have resulted in more than necessary loops in the while loop. Special-cased cases when (max + 1 == 0) to prevent the ceilLog2 functions from failing. --- src/base/random.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/base/random.cc b/src/base/random.cc index 457b0c98b..cffeddec9 100644 --- a/src/base/random.cc +++ b/src/base/random.cc @@ -29,6 +29,7 @@ * Ali Saidi */ +#include #include "base/fenv.hh" #include "base/intmath.hh" #include "base/misc.hh" @@ -67,7 +68,10 @@ Random::genrand(uint32_t max) { if (max == 0) return 0; - int log = ceilLog2(max) + 1; + if (max == std::numeric_limits::max()) + return genrand(); + + int log = ceilLog2(max + 1); int shift = (sizeof(uint32_t) * 8 - log); uint32_t random; @@ -83,7 +87,10 @@ Random::genrand(uint64_t max) { if (max == 0) return 0; - int log = ceilLog2(max) + 1; + if (max == std::numeric_limits::max()) + return genrand(); + + int log = ceilLog2(max + 1); int shift = (sizeof(uint64_t) * 8 - log); uint64_t random; -- cgit v1.2.3 From 80a6907927461241883a47b552272702978216f8 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: ARM: Add support for initparam m5 op --- src/arch/arm/isa/insts/m5ops.isa | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/arm/isa/insts/m5ops.isa b/src/arch/arm/isa/insts/m5ops.isa index 3b837cba9..f20908d4f 100644 --- a/src/arch/arm/isa/insts/m5ops.isa +++ b/src/arch/arm/isa/insts/m5ops.isa @@ -191,16 +191,18 @@ let {{ initparamCode = ''' #if FULL_SYSTEM - Rt = PseudoInst::initParam(xc->tcBase()); + uint64_t ip_val = PseudoInst::initParam(xc->tcBase()); + R0 = bits(ip_val, 31, 0); + R1 = bits(ip_val, 63, 32); #else PseudoInst::panicFsOnlyPseudoInst("initparam"); - Rt = 0; #endif ''' initparamIop = InstObjParams("initparam", "Initparam", "PredOp", { "code": initparamCode, - "predicate_test": predicateTest }) + "predicate_test": predicateTest }, + ["IsNonSpeculative"]) header_output += BasicDeclare.subst(initparamIop) decoder_output += BasicConstructor.subst(initparamIop) exec_output += PredOpExecute.subst(initparamIop) -- cgit v1.2.3 From bcb71963ebb3c226f4f36f6d5907c6fb3bc10b64 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: ARM: Add support for running multiple systems --- src/dev/arm/pl111.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/arm/pl111.cc b/src/dev/arm/pl111.cc index e13045338..958f07aa7 100644 --- a/src/dev/arm/pl111.cc +++ b/src/dev/arm/pl111.cc @@ -67,7 +67,7 @@ Pl111::Pl111(const Params *p) { pioSize = 0xFFFF; - pic = simout.create("framebuffer.bmp", true); + pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true); dmaBuffer = new uint8_t[LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t)]; -- cgit v1.2.3 From d2c26f402cfdb9a7fd34e98e3fc7aaa48c56c99b Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: O3: Add support of function tracing with O3 CPU. --- src/cpu/base.hh | 9 ++++----- src/cpu/o3/commit_impl.hh | 3 +++ 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cpu/base.hh b/src/cpu/base.hh index ce02889f3..638556deb 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -291,17 +291,16 @@ class BaseCPU : public MemObject void enableFunctionTrace(); void traceFunctionsInternal(Addr pc); - protected: + private: + static std::vector cpuList; //!< Static global cpu list + + public: void traceFunctions(Addr pc) { if (functionTracingEnabled) traceFunctionsInternal(pc); } - private: - static std::vector cpuList; //!< Static global cpu list - - public: static int numSimulatedCPUs() { return cpuList.size(); } static Counter numSimulatedInstructions() { diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 75ae87c75..9ff31a622 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -52,6 +52,7 @@ #include "config/use_checker.hh" #include "cpu/o3/commit.hh" #include "cpu/o3/thread_state.hh" +#include "cpu/base.hh" #include "cpu/exetrace.hh" #include "cpu/timebuf.hh" #include "debug/Activity.hh" @@ -992,6 +993,8 @@ DefaultCommit::commitInsts() // Updates misc. registers. head_inst->updateMiscRegs(); + cpu->traceFunctions(pc[tid].instAddr()); + TheISA::advancePC(pc[tid], head_inst->staticInst); // Keep track of the last sequence number commited -- cgit v1.2.3 From c94e5256d9d6a076118336a61b951bcf9b5482a1 Mon Sep 17 00:00:00 2001 From: Min Kyu Jeong Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: mem: Change DPRINTF prints more useful destination port number. Old code prints 0 for destination since pkt->getDest() returns 0 for pkt->getDest() == Packet::Broadcast, which is always true. --- src/mem/bus.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 69b14547e..db71b86b7 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -447,13 +447,6 @@ Bus::recvAtomic(PacketPtr pkt) void Bus::recvFunctional(PacketPtr pkt) { - if (!pkt->isPrint()) { - // don't do DPRINTFs on PrintReq as it clutters up the output - DPRINTF(Bus, - "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", - pkt->getSrc(), pkt->getDest(), pkt->getAddr(), - pkt->cmdString()); - } assert(pkt->getDest() == Packet::Broadcast); int port_id = findPort(pkt->getAddr()); @@ -462,6 +455,14 @@ Bus::recvFunctional(PacketPtr pkt) // id after each int src_id = pkt->getSrc(); + if (!pkt->isPrint()) { + // don't do DPRINTFs on PrintReq as it clutters up the output + DPRINTF(Bus, + "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", + src_id, port_id, pkt->getAddr(), + pkt->cmdString()); + } + assert(pkt->isRequest()); // hasn't already been satisfied SnoopIter s_end = snoopPorts.end(); -- cgit v1.2.3 From 68d387ec802083322196f609c755b993771e9d19 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: config: support outputing a pickle of the configuration tree --- src/python/m5/SimObject.py | 45 +++++++++++++++++++++++++++++++++++---------- src/python/m5/main.py | 2 ++ src/python/m5/params.py | 9 +++++++++ src/python/m5/simulate.py | 9 +++++++++ 4 files changed, 55 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 60693758c..dcc90e1bc 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -874,29 +874,54 @@ class SimObject(object): if hasattr(self, 'type'): print >>ini_file, 'type=%s' % self.type - child_names = self._children.keys() - child_names.sort() - if len(child_names): + if len(self._children.keys()): print >>ini_file, 'children=%s' % \ - ' '.join(self._children[n].get_name() for n in child_names) + ' '.join(self._children[n].get_name() \ + for n in sorted(self._children.keys())) - param_names = self._params.keys() - param_names.sort() - for param in param_names: + for param in sorted(self._params.keys()): value = self._values.get(param) if value != None: print >>ini_file, '%s=%s' % (param, self._values[param].ini_str()) - port_names = self._ports.keys() - port_names.sort() - for port_name in port_names: + for port_name in sorted(self._ports.keys()): port = self._port_refs.get(port_name, None) if port != None: print >>ini_file, '%s=%s' % (port_name, port.ini_str()) print >>ini_file # blank line between objects + # generate a tree of dictionaries expressing all the parameters in the + # instantiated system for use by scripts that want to do power, thermal + # visualization, and other similar tasks + def get_config_as_dict(self): + d = attrdict() + if hasattr(self, 'type'): + d.type = self.type + if hasattr(self, 'cxx_class'): + d.cxx_class = self.cxx_class + + for param in sorted(self._params.keys()): + value = self._values.get(param) + try: + d[param] = self._values[param].value + except AttributeError: + pass + + for n in sorted(self._children.keys()): + d[self._children[n].get_name()] = self._children[n].get_config_as_dict() + + for port_name in sorted(self._ports.keys()): + port = self._port_refs.get(port_name, None) + if port != None: + # Might want to actually make this reference the object + # in the future, although execing the string problem would + # get some of the way there + d[port_name] = port.ini_str() + + return d + def getCCParams(self): if self._ccParams: return self._ccParams diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 58de62cc3..17e0c2f91 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -87,6 +87,8 @@ def parse_options(): group("Configuration Options") option("--dump-config", metavar="FILE", default="config.ini", help="Dump configuration output file [Default: %default]") + option("--json-config", metavar="FILE", default="config.json", + help="Create JSON output of the configuration [Default: %default]") # Debugging options group("Debugging Options") diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 03917d085..05fe9b774 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -228,6 +228,12 @@ class SimObjectVector(VectorParamValue): for obj in v.descendants(): yield obj + def get_config_as_dict(self): + a = [] + for v in self: + a.append(v.get_config_as_dict()) + return a + class VectorParamDesc(ParamDesc): # Convert assigned value to appropriate type. If the RHS is not a # list or tuple, it generates a single-element list. @@ -964,6 +970,9 @@ class Time(ParamValue): def ini_str(self): return str(self) + def get_config_as_dict(self): + return str(self) + # Enumerated types are a little more complex. The user specifies the # type as Enum(foo) where foo is either a list or dictionary of # alternatives (typically strings, but not necessarily so). (In the diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index b4ccf82c1..29d14f75d 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -31,6 +31,7 @@ import atexit import os import sys +import json # import the SWIG-wrapped main C++ functions import internal @@ -40,6 +41,7 @@ import SimObject import ticks import objects from util import fatal +from util import attrdict # define a MaxTick parameter MaxTick = 2**63 - 1 @@ -71,6 +73,13 @@ def instantiate(ckpt_dir=None): obj.print_ini(ini_file) ini_file.close() + if options.json_config: + json_file = file(os.path.join(options.outdir, options.json_config), 'w') + d = root.get_config_as_dict() + json.dump(d, json_file, indent=4) + json_file.close() + + # Initialize the global statistics stats.initSimStats() -- cgit v1.2.3 From 525d1e46dcb3180c8d73996adc025ce255575bd7 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: O3: Remove some asserts that no longer seem to be valid. --- src/cpu/o3/decode_impl.hh | 4 ---- src/cpu/o3/rename_impl.hh | 4 ---- 2 files changed, 8 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 0c0ec768e..a523a8b45 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -447,10 +447,6 @@ void DefaultDecode::sortInsts() { int insts_from_fetch = fromFetch->size; -#ifdef DEBUG - for (ThreadID tid = 0; tid < numThreads; tid++) - assert(insts[tid].empty()); -#endif for (int i = 0; i < insts_from_fetch; ++i) { insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]); } diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index fc93a5197..98c0f231b 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -767,10 +767,6 @@ void DefaultRename::sortInsts() { int insts_from_decode = fromDecode->size; -#ifdef DEBUG - for (ThreadID tid = 0; tid < numThreads; tid++) - assert(insts[tid].empty()); -#endif for (int i = 0; i < insts_from_decode; ++i) { DynInstPtr inst = fromDecode->insts[i]; insts[inst->threadNumber].push_back(inst); -- cgit v1.2.3 From 51aa7e4a0392d5e8f98bd7a4d09f4026dd21bd0a Mon Sep 17 00:00:00 2001 From: Prakash Ramrakhyani Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: sim: Enable sampling of run-time for code-sections marked using pseudo insts. This patch adds a mechanism to collect run time samples for specific portions of a benchmark, using work_begin and work_end pseudo instructions.It also enhances the histogram stat to report geometric mean. --- src/base/statistics.hh | 5 +++++ src/base/stats/info.hh | 1 + src/base/stats/text.cc | 6 ++++++ src/python/m5/main.py | 1 - src/sim/System.py | 2 +- src/sim/pseudo_inst.cc | 2 ++ src/sim/system.cc | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- src/sim/system.hh | 14 +++++++++++++- 8 files changed, 77 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index d98c79414..1f8a59326 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -1477,6 +1477,8 @@ class HistStor /** The current sum. */ Counter sum; + /** The sum of logarithm of each sample, used to compute geometric mean. */ + Counter logs; /** The sum of squares. */ Counter squares; /** The number of samples. */ @@ -1528,6 +1530,7 @@ class HistStor sum += val * number; squares += val * val * number; + logs += log(val) * number; samples += number; } @@ -1567,6 +1570,7 @@ class HistStor data.cvec[i] = cvec[i]; data.sum = sum; + data.logs = logs; data.squares = squares; data.samples = samples; } @@ -1589,6 +1593,7 @@ class HistStor sum = Counter(); squares = Counter(); samples = Counter(); + logs = Counter(); } }; diff --git a/src/base/stats/info.hh b/src/base/stats/info.hh index 2c5b44a38..98e811747 100644 --- a/src/base/stats/info.hh +++ b/src/base/stats/info.hh @@ -183,6 +183,7 @@ struct DistData VCounter cvec; Counter sum; Counter squares; + Counter logs; Counter samples; }; diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 683ba7fe4..4cf98ca9e 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -367,6 +367,12 @@ DistPrint::operator()(ostream &stream) const print.value = data.samples ? data.sum / data.samples : NAN; print(stream); + if (data.type == Hist) { + print.name = base + "gmean"; + print.value = data.samples ? exp(data.logs / data.samples) : NAN; + print(stream); + } + Result stdev = NAN; if (data.samples) stdev = sqrt((data.samples * data.squares - data.sum * data.sum) / diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 17e0c2f91..910cb6ce6 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -123,7 +123,6 @@ def parse_options(): execfile(options_file, scope) arguments = options.parse_args() - return options,arguments def interact(scope): diff --git a/src/sim/System.py b/src/sim/System.py index d9836211f..3caa907d7 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -54,8 +54,8 @@ class System(SimObject): physmem = Param.PhysicalMemory("Physical Memory") mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in") memories = VectorParam.PhysicalMemory(Self.all, "All memories is the system") - work_item_id = Param.Int(-1, "specific work item id") + num_work_ids = Param.Int(16, "Number of distinct work item types") work_begin_cpu_id_exit = Param.Int(-1, "work started on specific id, now exit simulation") work_begin_ckpt_count = Param.Counter(0, diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 2062dfb8c..647420ca1 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -383,6 +383,7 @@ workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid) tc->getCpuPtr()->workItemBegin(); System *sys = tc->getSystemPtr(); const System::Params *params = sys->params(); + sys->workItemBegin(threadid, workid); DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid, threadid); @@ -439,6 +440,7 @@ workend(ThreadContext *tc, uint64_t workid, uint64_t threadid) tc->getCpuPtr()->workItemEnd(); System *sys = tc->getSystemPtr(); const System::Params *params = sys->params(); + sys->workItemEnd(threadid, workid); DPRINTF(WorkItems, "Work End workid: %d, threadid %d\n", workid, threadid); diff --git a/src/sim/system.cc b/src/sim/system.cc index c58830c10..556a919d5 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2003-2006 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -43,6 +55,7 @@ #include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "debug/Loader.hh" +#include "debug/WorkItems.hh" #include "mem/mem_object.hh" #include "mem/physical.hh" #include "sim/byteswap.hh" @@ -76,8 +89,9 @@ System::System(Params *p) memoryMode(p->mem_mode), workItemsBegin(0), workItemsEnd(0), + numWorkIds(p->num_work_ids), _params(p), - totalNumInsts(0), + totalNumInsts(0), instEventQueue("system instruction-based event queue") { // add self to global system list @@ -171,6 +185,9 @@ System::~System() panic("System::fixFuncEventAddr needs to be rewritten " "to work with syscall emulation"); #endif // FULL_SYSTEM} + + for (uint32_t j = 0; j < numWorkIds; j++) + delete workItemStats[j]; } void @@ -339,6 +356,37 @@ System::unserialize(Checkpoint *cp, const string §ion) #endif } +void +System::regStats() +{ + for (uint32_t j = 0; j < numWorkIds ; j++) { + workItemStats[j] = new Stats::Histogram(); + stringstream namestr; + ccprintf(namestr, "work_item_type%d", j); + workItemStats[j]->init(20) + .name(name() + "." + namestr.str()) + .desc("Run time stat for" + namestr.str()) + .prereq(*workItemStats[j]); + } +} + +void +System::workItemEnd(uint32_t tid, uint32_t workid) +{ + std::pair p(tid, workid); + if (!lastWorkItemStarted.count(p)) + return; + + Tick samp = curTick() - lastWorkItemStarted[p]; + DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp); + + if (workid >= numWorkIds) + fatal("Got workid greater than specified in system configuration\n"); + + workItemStats[workid]->sample(samp); + lastWorkItemStarted.erase(p); +} + void System::printSystems() { diff --git a/src/sim/system.hh b/src/sim/system.hh index ed5193dfd..44383c399 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -171,14 +171,16 @@ class System : public SimObject Enums::MemoryMode memoryMode; uint64_t workItemsBegin; uint64_t workItemsEnd; + uint32_t numWorkIds; std::vector activeCpus; public: + virtual void regStats(); /** * Called by pseudo_inst to track the number of work items started by this * system. */ - uint64_t + uint64_t incWorkItemsBegin() { return ++workItemsBegin; @@ -212,6 +214,14 @@ class System : public SimObject return count; } + inline void workItemBegin(uint32_t tid, uint32_t workid) + { + std::pair p(tid, workid); + lastWorkItemStarted[p] = curTick(); + } + + void workItemEnd(uint32_t tid, uint32_t workid); + #if FULL_SYSTEM /** * Fix up an address used to match PCs for hooking simulator @@ -303,6 +313,8 @@ class System : public SimObject public: Counter totalNumInsts; EventQueue instEventQueue; + std::map, Tick> lastWorkItemStarted; + std::map workItemStats; //////////////////////////////////////////// // -- cgit v1.2.3 From bda1125e882eaf8c127ebdae0d847bf2148832ad Mon Sep 17 00:00:00 2001 From: Dam Sunwoo Date: Mon, 9 Jan 2012 18:08:20 -0600 Subject: stats: fix Vector2d to display stats correctly when y_subname is not specified. Vector2d stats with no y_subname were not displayed as the VectorPrint subname was not initialized correctly to reflect the empty field. --- src/base/stats/text.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 4cf98ca9e..8fb49dc59 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -513,7 +513,14 @@ Text::visit(const Vector2dInfo &info) bool havesub = false; VectorPrint print; - print.subnames = info.y_subnames; + if (!info.y_subnames.empty()) { + for (off_type i = 0; i < info.y; ++i) { + if (!info.y_subnames[i].empty()) { + print.subnames = info.y_subnames; + } + break; + } + } print.flags = info.flags; print.separatorString = info.separatorString; print.descriptions = descriptions; -- cgit v1.2.3 From e826d23a2eae6136f20f74d8d48601ff49349e58 Mon Sep 17 00:00:00 2001 From: Geoffrey Blake Date: Mon, 9 Jan 2012 18:10:05 -0600 Subject: Packet: Add derived class FunctionalPacket to enable partial functional reads This adds the derived class FunctionalPacket to fix a long standing deficiency in the Packet class where it was unable to handle finding data to partially satisfy a functional access. Made this a derived class as functional accesses are used only in certain contexts and to not add any additional overhead to the existing Packet class. --- src/mem/packet.cc | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++---- src/mem/packet.hh | 15 +++++++- 2 files changed, 118 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 5ec977ed4..57d85af8a 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * Copyright (c) 2010 Advanced Micro Devices, Inc. * All rights reserved. @@ -192,14 +204,99 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) memcpy(getPtr(), data + offset, getSize()); return true; } else { - // In this case the timing packet only partially satisfies - // the request, so we would need more information to make - // this work. Like bytes valid in the packet or - // something, so the request could continue and get this - // bit of possibly newer data along with the older data - // not written to yet. - panic("Memory value only partially satisfies the functional " - "request. Now what?"); + // Offsets and sizes to copy in case of partial overlap + int func_offset; + int val_offset; + int overlap_size; + + // calculate offsets and copy sizes for the two byte arrays + if (val_start < func_start && val_end <= func_end) { + val_offset = func_start - val_start; + func_offset = 0; + overlap_size = val_end - func_start; + } else if (val_start >= func_start && val_end > func_end) { + val_offset = 0; + func_offset = val_start - func_start; + overlap_size = func_end - val_start; + } else if (val_start >= func_start && val_end <= func_end) { + val_offset = 0; + func_offset = val_start - func_start; + overlap_size = size; + } else { + panic("BUG: Missed a case for a partial functional request"); + } + + // Figure out how much of the partial overlap should be copied + // into the packet and not overwrite previously found bytes. + if (bytesValidStart == 0 && bytesValidEnd == 0) { + // No bytes have been copied yet, just set indices + // to found range + bytesValidStart = func_offset; + bytesValidEnd = func_offset + overlap_size; + } else { + // Some bytes have already been copied. Use bytesValid + // indices and offset values to figure out how much data + // to copy and where to copy it to. + + // Indice overlap conditions to check + int a = func_offset - bytesValidStart; + int b = (func_offset + overlap_size) - bytesValidEnd; + int c = func_offset - bytesValidEnd; + int d = (func_offset + overlap_size) - bytesValidStart; + + if (a >= 0 && b <= 0) { + // bytes already in pkt data array are superset of + // found bytes, will not copy any bytes + overlap_size = 0; + } else if (a < 0 && d >= 0 && b <= 0) { + // found bytes will move bytesValidStart towards 0 + overlap_size = bytesValidStart - func_offset; + bytesValidStart = func_offset; + } else if (b > 0 && c <= 0 && a >= 0) { + // found bytes will move bytesValidEnd + // towards end of pkt data array + overlap_size = + (func_offset + overlap_size) - bytesValidEnd; + val_offset += bytesValidEnd - func_offset; + func_offset = bytesValidEnd; + bytesValidEnd += overlap_size; + } else if (a < 0 && b > 0) { + // Found bytes are superset of copied range. Will move + // bytesValidStart towards 0 and bytesValidEnd towards + // end of pkt data array. Need to break copy into two + // pieces so as to not overwrite previously found data. + + // copy the first half + uint8_t *dest = getPtr() + func_offset; + uint8_t *src = data + val_offset; + memcpy(dest, src, (bytesValidStart - func_offset)); + + // re-calc the offsets and indices to do the copy + // required for the second half + val_offset += (bytesValidEnd - func_offset); + bytesValidStart = func_offset; + overlap_size = + (func_offset + overlap_size) - bytesValidEnd; + func_offset = bytesValidEnd; + bytesValidEnd += overlap_size; + } else if ((c > 0 && b > 0) + || (a < 0 && d < 0)) { + // region to be copied is discontiguous! Not supported. + panic("BUG: Discontiguous bytes found" + "for functional copying!"); + } + } + + assert((bytesValidStart >= 0) && (bytesValidEnd <= getSize())); + + // copy partial data into the packet's data array + uint8_t *dest = getPtr() + func_offset; + uint8_t *src = data + val_offset; + memcpy(dest, src, overlap_size); + + // check if we're done filling the functional access + bool done = (bytesValidStart == 0) && (bytesValidEnd == getSize()); + return done; } } else if (isWrite()) { if (offset >= 0) { diff --git a/src/mem/packet.hh b/src/mem/packet.hh index be0c20d42..6347c21ea 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -299,6 +299,13 @@ class Packet : public FastAlloc, public Printable */ MemCmd origCmd; + /** + * These values specify the range of bytes found that satisfy a + * functional read. + */ + uint16_t bytesValidStart; + uint16_t bytesValidEnd; + public: /// Used to calculate latencies for each packet. Tick time; @@ -507,7 +514,8 @@ class Packet : public FastAlloc, public Printable */ Packet(Request *_req, MemCmd _cmd, NodeID _dest) : flags(VALID_DST), cmd(_cmd), req(_req), data(NULL), - dest(_dest), time(curTick()), senderState(NULL) + dest(_dest), bytesValidStart(0), bytesValidEnd(0), + time(curTick()), senderState(NULL) { if (req->hasPaddr()) { addr = req->getPaddr(); @@ -526,7 +534,8 @@ class Packet : public FastAlloc, public Printable */ Packet(Request *_req, MemCmd _cmd, NodeID _dest, int _blkSize) : flags(VALID_DST), cmd(_cmd), req(_req), data(NULL), - dest(_dest), time(curTick()), senderState(NULL) + dest(_dest), bytesValidStart(0), bytesValidEnd(0), + time(curTick()), senderState(NULL) { if (req->hasPaddr()) { addr = req->getPaddr() & ~(_blkSize - 1); @@ -547,6 +556,7 @@ class Packet : public FastAlloc, public Printable : cmd(pkt->cmd), req(pkt->req), data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL), addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest), + bytesValidStart(pkt->bytesValidStart), bytesValidEnd(pkt->bytesValidEnd), time(curTick()), senderState(pkt->senderState) { if (!clearFlags) @@ -554,6 +564,7 @@ class Packet : public FastAlloc, public Printable flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE|VALID_SRC|VALID_DST)); flags.set(pkt->flags & STATIC_DATA); + } /** -- cgit v1.2.3 From e308208f302b6bccff15f7c694e7ed334e870942 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 9 Jan 2012 20:04:28 -0500 Subject: Config: Fix issue with JSON output --- src/python/m5/SimObject.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index dcc90e1bc..47ca32af2 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -905,7 +905,15 @@ class SimObject(object): for param in sorted(self._params.keys()): value = self._values.get(param) try: - d[param] = self._values[param].value + # Use native type for those supported by JSON and + # strings for everything else. skipkeys=True seems + # to not work as well as one would hope + if type(self._values[param].value) in \ + [str, unicode, int, long, float, bool, None]: + d[param] = self._values[param].value + else: + d[param] = str(self._values[param]) + except AttributeError: pass -- cgit v1.2.3 From b587d511c3819576ce1195b59416083cbd42522a Mon Sep 17 00:00:00 2001 From: Anders Handler Date: Mon, 9 Jan 2012 20:05:07 -0500 Subject: CPU: Remove Alpha-specific PC alignment check. --- src/cpu/pc_event.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cpu/pc_event.cc b/src/cpu/pc_event.cc index f9955d014..385a83b27 100644 --- a/src/cpu/pc_event.cc +++ b/src/cpu/pc_event.cc @@ -84,7 +84,9 @@ PCEventQueue::schedule(PCEvent *event) bool PCEventQueue::doService(ThreadContext *tc) { - Addr pc = tc->instAddr() & ~0x3; + // This will fail to break on Alpha PALcode addresses, but that is + // a rare use case. + Addr pc = tc->instAddr(); int serviced = 0; range_t range = equal_range(pc); for (iterator i = range.first; i != range.second; ++i) { @@ -92,7 +94,7 @@ PCEventQueue::doService(ThreadContext *tc) // another event. This for example, prevents two invocations // of the SkipFuncEvent. Maybe we should have separate PC // event queues for each processor? - if (pc != (tc->instAddr() & ~0x3)) + if (pc != tc->instAddr()) continue; DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n", -- cgit v1.2.3 From acbc03ae464b027fe93dca3a0bc796ef63f53113 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Mon, 9 Jan 2012 20:13:31 -0600 Subject: X86: Add memory fence to I/O instructions --- src/arch/x86/isa/insts/general_purpose/input_output/general_io.py | 8 ++++++++ src/arch/x86/isa/insts/general_purpose/input_output/string_io.py | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py index c034f8a48..0465b3447 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py @@ -42,26 +42,34 @@ microcode = ''' def macroop IN_R_I { .adjust_imm trimImm(8) limm t1, imm, dataSize=asz + mfence ld reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=8, \ nonSpec=True + mfence }; def macroop IN_R_R { zexti t2, regm, 15, dataSize=8 + mfence ld reg, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8, \ nonSpec=True + mfence }; def macroop OUT_I_R { .adjust_imm trimImm(8) limm t1, imm, dataSize=8 + mfence st reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=8, \ nonSpec=True + mfence }; def macroop OUT_R_R { zexti t2, reg, 15, dataSize=8 + mfence st regm, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8, \ nonSpec=True + mfence }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py index 3c90ee7e7..044e57edc 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py @@ -45,9 +45,11 @@ def macroop INS_M_R { zexti t2, reg, 15, dataSize=8 + mfence ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8, \ nonSpec=True st t6, es, [1, t0, rdi] + mfence add rdi, rdi, t3, dataSize=asz }; @@ -63,6 +65,7 @@ def macroop INS_E_M_R { zexti t2, reg, 15, dataSize=8 + mfence topOfLoop: ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8, \ nonSpec=True @@ -72,6 +75,7 @@ topOfLoop: add rdi, rdi, t3, dataSize=asz br label("topOfLoop"), flags=(nCEZF,) end: + mfence fault "NoFault" }; @@ -84,9 +88,11 @@ def macroop OUTS_R_M { zexti t2, reg, 15, dataSize=8 + mfence ld t6, ds, [1, t0, rsi] st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8, \ nonSpec=True + mfence add rsi, rsi, t3, dataSize=asz }; @@ -102,6 +108,7 @@ def macroop OUTS_E_R_M { zexti t2, reg, 15, dataSize=8 + mfence topOfLoop: ld t6, ds, [1, t0, rsi] st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8, \ @@ -111,6 +118,7 @@ topOfLoop: add rsi, rsi, t3, dataSize=asz br label("topOfLoop"), flags=(nCEZF,) end: + mfence fault "NoFault" }; ''' -- cgit v1.2.3 From 9957035a42653a0666e30c744ab02fb0074db3a3 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Tue, 10 Jan 2012 10:15:02 -0600 Subject: DPRINTF: Improve some dprintf messages. --- src/cpu/o3/iew_impl.hh | 6 +++--- src/dev/io_device.cc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 9c4b1068d..92c8875e4 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -1340,10 +1340,10 @@ DefaultIEW::executeInsts() fetchRedirect[tid] = true; DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); - DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", - inst->predInstAddr(), inst->predNextInstAddr()); + DPRINTF(IEW, "Predicted target was PC: %s.\n", + inst->readPredTarg()); DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n", - inst->pcState(), inst->nextInstAddr()); + inst->pcState()); // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index dab1f766e..00e463de1 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -71,7 +71,7 @@ void PioDevice::init() { if (!pioPort) - panic("Pio port not connected to anything!"); + panic("Pio port of %s not connected to anything!", name()); pioPort->sendStatusChange(Port::RangeChange); } -- cgit v1.2.3 From 8f18898e85ade3233502acd0dbc7cf9cd416d880 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 10 Jan 2012 10:17:33 -0600 Subject: config: Fix json output for Python lt 2.6. --- src/python/m5/simulate.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 29d14f75d..38129592c 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -31,7 +31,6 @@ import atexit import os import sys -import json # import the SWIG-wrapped main C++ functions import internal @@ -74,10 +73,14 @@ def instantiate(ckpt_dir=None): ini_file.close() if options.json_config: - json_file = file(os.path.join(options.outdir, options.json_config), 'w') - d = root.get_config_as_dict() - json.dump(d, json_file, indent=4) - json_file.close() + try: + import json + json_file = file(os.path.join(options.outdir, options.json_config), 'w') + d = root.get_config_as_dict() + json.dump(d, json_file, indent=4) + json_file.close() + except ImportError: + pass # Initialize the global statistics -- cgit v1.2.3 From adff204c976fb821ac3f2d3545fc28e3fa30c088 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Tue, 10 Jan 2012 10:20:32 -0600 Subject: Sparse Memory: Simplify the structure for an entry The SparseMemEntry structure includes just one void* pointer. It seems unnecessary that we have a structure for this. The patch removes the structure and makes use of a typedef on void* instead. --- src/mem/ruby/system/SparseMemory.cc | 31 ++++++++++++++----------------- src/mem/ruby/system/SparseMemory.hh | 14 +------------- 2 files changed, 15 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/mem/ruby/system/SparseMemory.cc b/src/mem/ruby/system/SparseMemory.cc index 8e4f37c46..0cfd0d90c 100644 --- a/src/mem/ruby/system/SparseMemory.cc +++ b/src/mem/ruby/system/SparseMemory.cc @@ -82,19 +82,19 @@ SparseMemory::recursivelyRemoveTables(SparseMapType* curTable, int curLevel) SparseMapType::iterator iter; for (iter = curTable->begin(); iter != curTable->end(); iter++) { - SparseMemEntry* entryStruct = &((*iter).second); + SparseMemEntry entry = (*iter).second; if (curLevel != (m_number_of_levels - 1)) { // If the not at the last level, analyze those lower level // tables first, then delete those next tables - SparseMapType* nextTable = (SparseMapType*)(entryStruct->entry); + SparseMapType* nextTable = (SparseMapType*)(entry); recursivelyRemoveTables(nextTable, (curLevel + 1)); delete nextTable; } else { // If at the last level, delete the directory entry - delete (AbstractEntry*)(entryStruct->entry); + delete (AbstractEntry*)(entry); } - entryStruct->entry = NULL; + entry = NULL; } // Once all entries have been deleted, erase the entries @@ -134,7 +134,7 @@ SparseMemory::exist(const Address& address) const // If the address is found, move on to the next level. // Otherwise, return not found if (curTable->count(curAddress) != 0) { - curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); + curTable = (SparseMapType*)((*curTable)[curAddress]); } else { DPRINTF(RubyCache, "Not found\n"); return false; @@ -156,7 +156,6 @@ SparseMemory::add(const Address& address, AbstractEntry* entry) Address curAddress; SparseMapType* curTable = m_map_head; - SparseMemEntry* entryStruct = NULL; // Initiallize the high bit to be the total number of bits plus // the block offset. However the highest bit index is one less @@ -179,7 +178,7 @@ SparseMemory::add(const Address& address, AbstractEntry* entry) // if the address exists in the cur table, move on. Otherwise // create a new table. if (curTable->count(curAddress) != 0) { - curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); + curTable = (SparseMapType*)((*curTable)[curAddress]); } else { m_adds_per_level[level]++; @@ -194,9 +193,7 @@ SparseMemory::add(const Address& address, AbstractEntry* entry) // Create the pointer container SparseMemEntry and add it // to the table. - entryStruct = new SparseMemEntry; - entryStruct->entry = newEntry; - (*curTable)[curAddress] = *entryStruct; + (*curTable)[curAddress] = newEntry; // Move to the next level of the heirarchy curTable = (SparseMapType*)newEntry; @@ -215,7 +212,7 @@ SparseMemory::recursivelyRemoveLevels(const Address& address, { Address curAddress; CurNextInfo nextInfo; - SparseMemEntry* entryStruct; + SparseMemEntry entry; // create the appropriate address for this level // Note: that set Address is inclusive of the specified range, @@ -231,11 +228,11 @@ SparseMemory::recursivelyRemoveLevels(const Address& address, assert(curInfo.curTable->count(curAddress) != 0); - entryStruct = &((*(curInfo.curTable))[curAddress]); + entry = (*(curInfo.curTable))[curAddress]; if (curInfo.level < (m_number_of_levels - 1)) { // set up next level's info - nextInfo.curTable = (SparseMapType*)(entryStruct->entry); + nextInfo.curTable = (SparseMapType*)(entry); nextInfo.level = curInfo.level + 1; nextInfo.highBit = curInfo.highBit - @@ -252,15 +249,15 @@ SparseMemory::recursivelyRemoveLevels(const Address& address, if (tableSize == 0) { m_removes_per_level[curInfo.level]++; delete nextInfo.curTable; - entryStruct->entry = NULL; + entry = NULL; curInfo.curTable->erase(curAddress); } } else { // if this is the last level, we have reached the Directory // Entry and thus we should delete it including the // SparseMemEntry container struct. - delete (AbstractEntry*)(entryStruct->entry); - entryStruct->entry = NULL; + delete (AbstractEntry*)(entry); + entry = NULL; curInfo.curTable->erase(curAddress); m_removes_per_level[curInfo.level]++; } @@ -331,7 +328,7 @@ SparseMemory::lookup(const Address& address) // If the address is found, move on to the next level. // Otherwise, return not found if (curTable->count(curAddress) != 0) { - curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); + curTable = (SparseMapType*)((*curTable)[curAddress]); } else { DPRINTF(RubyCache, "Not found\n"); return NULL; diff --git a/src/mem/ruby/system/SparseMemory.hh b/src/mem/ruby/system/SparseMemory.hh index f6937ef54..f4cc12f97 100644 --- a/src/mem/ruby/system/SparseMemory.hh +++ b/src/mem/ruby/system/SparseMemory.hh @@ -36,11 +36,7 @@ #include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Global.hh" -struct SparseMemEntry -{ - void* entry; -}; - +typedef void* SparseMemEntry; typedef m5::hash_map SparseMapType; struct CurNextInfo @@ -95,12 +91,4 @@ class SparseMemory uint64_t* m_removes_per_level; }; -inline std::ostream& -operator<<(std::ostream& out, const SparseMemEntry& obj) -{ - out << "SparseMemEntry"; - out << std::flush; - return out; -} - #endif // __MEM_RUBY_SYSTEM_SPARSEMEMORY_HH__ -- cgit v1.2.3 From 70cb16ba14d77031d6f642ac253877a57cfdbce9 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Tue, 10 Jan 2012 17:28:44 -0600 Subject: MOESI Hammer: Remove a couple of bugs A couple of bugs were observed while building checkpointing support in Ruby. This patch changes transitions to remove those errors. --- src/mem/protocol/MOESI_hammer-cache.sm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/mem/protocol/MOESI_hammer-cache.sm b/src/mem/protocol/MOESI_hammer-cache.sm index b9d355736..ce16a8777 100644 --- a/src/mem/protocol/MOESI_hammer-cache.sm +++ b/src/mem/protocol/MOESI_hammer-cache.sm @@ -1285,7 +1285,6 @@ machine(L1Cache, "AMD Hammer-like protocol") vv_allocateL2CacheBlock; hp_copyFromTBEToL2; s_deallocateTBE; - ka_wakeUpAllDependents; } transition(I, Trigger_L2_to_L1D, IT) { @@ -1566,7 +1565,7 @@ machine(L1Cache, "AMD Hammer-like protocol") k_popMandatoryQueue; } - transition({MM, M, MMR}, Flush_line, MM_F) { + transition({MM, M, MMR, MR}, Flush_line, MM_F) { i_allocateTBE; bf_issueGETF; p_decrementNumberOfMessagesByOne; -- cgit v1.2.3 From bd739a75b99c110008114f1079a41c743e65da84 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Tue, 10 Jan 2012 18:35:45 -0600 Subject: Ruby: remove the files related to the tracer The Ruby Tracer is out of date with the changes that are being carried out to support checkpointing. Hence, it needs to be removed. --- src/mem/ruby/recorder/SConscript | 3 - src/mem/ruby/recorder/Tracer.cc | 135 --------------------------------------- src/mem/ruby/recorder/Tracer.hh | 86 ------------------------- src/mem/ruby/recorder/Tracer.py | 37 ----------- src/mem/ruby/system/Sequencer.cc | 2 - src/mem/ruby/system/System.cc | 9 --- src/mem/ruby/system/System.hh | 10 --- 7 files changed, 282 deletions(-) delete mode 100644 src/mem/ruby/recorder/Tracer.cc delete mode 100644 src/mem/ruby/recorder/Tracer.hh delete mode 100644 src/mem/ruby/recorder/Tracer.py (limited to 'src') diff --git a/src/mem/ruby/recorder/SConscript b/src/mem/ruby/recorder/SConscript index 035f896a4..4258d2c47 100644 --- a/src/mem/ruby/recorder/SConscript +++ b/src/mem/ruby/recorder/SConscript @@ -33,8 +33,5 @@ Import('*') if env['PROTOCOL'] == 'None': Return() -SimObject('Tracer.py') - Source('CacheRecorder.cc') -Source('Tracer.cc') Source('TraceRecord.cc', Werror=False) diff --git a/src/mem/ruby/recorder/Tracer.cc b/src/mem/ruby/recorder/Tracer.cc deleted file mode 100644 index fcfe5338c..000000000 --- a/src/mem/ruby/recorder/Tracer.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * 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. - */ - -#include "base/cprintf.hh" -#include "mem/ruby/eventqueue/RubyEventQueue.hh" -#include "mem/ruby/recorder/TraceRecord.hh" -#include "mem/ruby/recorder/Tracer.hh" -#include "mem/ruby/system/System.hh" - -using namespace std; - -Tracer::Tracer(const Params *p) - : SimObject(p) -{ - m_enabled = false; - m_warmup_length = p->warmup_length; - assert(m_warmup_length > 0); - p->ruby_system->registerTracer(this); -} - -void -Tracer::startTrace(string filename) -{ - if (m_enabled) - stopTrace(); - - if (filename != "") { - m_trace_file.open(filename.c_str()); - if (m_trace_file.fail()) { - cprintf("Error: error opening file '%s'\n", filename); - cprintf("Trace not enabled.\n"); - return; - } - cprintf("Request trace enabled to output file '%s'\n", filename); - m_enabled = true; - } -} - -void -Tracer::stopTrace() -{ - if (m_enabled) { - m_trace_file.close(); - cout << "Request trace file closed." << endl; - m_enabled = false; - } -} - -void -Tracer::traceRequest(Sequencer* sequencer, const Address& data_addr, - const Address& pc_addr, RubyRequestType type, Time time) -{ - assert(m_enabled); - TraceRecord tr(sequencer, data_addr, pc_addr, type, time); - tr.output(m_trace_file); -} - -int -Tracer::playbackTrace(string filename) -{ - igzstream in(filename.c_str()); - if (in.fail()) { - cprintf("Error: error opening file '%s'\n", filename); - return 0; - } - - time_t start_time = time(NULL); - - TraceRecord record; - int counter = 0; - // Read in the next TraceRecord - bool ok = record.input(in); - while (ok) { - // Put it in the right cache - record.issueRequest(); - counter++; - - // Read in the next TraceRecord - ok = record.input(in); - - // Clear the statistics after warmup - if (counter == m_warmup_length) { - cprintf("Clearing stats after warmup of length %s\n", - m_warmup_length); - g_system_ptr->clearStats(); - } - } - - // Flush the prefetches through the system - // FIXME - should be smarter - g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 1000); - - time_t stop_time = time(NULL); - double seconds = difftime(stop_time, start_time); - double minutes = seconds / 60.0; - cout << "playbackTrace: " << minutes << " minutes" << endl; - - return counter; -} - -void -Tracer::print(ostream& out) const -{ -} - -Tracer * -RubyTracerParams::create() -{ - return new Tracer(this); -} diff --git a/src/mem/ruby/recorder/Tracer.hh b/src/mem/ruby/recorder/Tracer.hh deleted file mode 100644 index cad47b28c..000000000 --- a/src/mem/ruby/recorder/Tracer.hh +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * 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. - */ - -/* - * Controller class of the tracer. Can stop/start/playback the ruby - * cache requests trace. - */ - -#ifndef __MEM_RUBY_RECORDER_TRACER_HH__ -#define __MEM_RUBY_RECORDER_TRACER_HH__ - -#include -#include - -#include "mem/protocol/RubyRequestType.hh" -#include "mem/ruby/common/Global.hh" -#include "params/RubyTracer.hh" -#include "sim/sim_object.hh" -#include "gzstream.hh" - -class Address; -class TraceRecord; -class Sequencer; - -class Tracer : public SimObject -{ - public: - typedef RubyTracerParams Params; - Tracer(const Params *p); - - void startTrace(std::string filename); - void stopTrace(); - bool traceEnabled() { return m_enabled; } - void traceRequest(Sequencer* sequencer, const Address& data_addr, - const Address& pc_addr, RubyRequestType type, Time time); - - void print(std::ostream& out) const; - - int playbackTrace(std::string filename); - - private: - // Private copy constructor and assignment operator - Tracer(const Tracer& obj); - Tracer& operator=(const Tracer& obj); - - ogzstream m_trace_file; - bool m_enabled; - - //added by SS - int m_warmup_length; -}; - -inline std::ostream& -operator<<(std::ostream& out, const Tracer& obj) -{ - obj.print(out); - out << std::flush; - return out; -} - -#endif // __MEM_RUBY_RECORDER_TRACER_HH__ diff --git a/src/mem/ruby/recorder/Tracer.py b/src/mem/ruby/recorder/Tracer.py deleted file mode 100644 index 7a689f9f7..000000000 --- a/src/mem/ruby/recorder/Tracer.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2009 Advanced Micro Devices, Inc. -# 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 -# Brad Beckmann - -from m5.params import * -from m5.SimObject import SimObject - -class RubyTracer(SimObject): - type = 'RubyTracer' - cxx_class = 'Tracer' - warmup_length = Param.Int(100000, "") - ruby_system = Param.RubySystem("") diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index 7137dcc28..f489e3461 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -40,9 +40,7 @@ #include "mem/protocol/RubyAccessMode.hh" #include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/common/Global.hh" -#include "mem/ruby/common/SubBlock.hh" #include "mem/ruby/profiler/Profiler.hh" -#include "mem/ruby/recorder/Tracer.hh" #include "mem/ruby/slicc_interface/RubyRequest.hh" #include "mem/ruby/system/CacheMemory.hh" #include "mem/ruby/system/Sequencer.hh" diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc index 81824b9b7..abba4eedc 100644 --- a/src/mem/ruby/system/System.cc +++ b/src/mem/ruby/system/System.cc @@ -32,7 +32,6 @@ #include "mem/ruby/common/Address.hh" #include "mem/ruby/network/Network.hh" #include "mem/ruby/profiler/Profiler.hh" -#include "mem/ruby/recorder/Tracer.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" #include "mem/ruby/system/MemoryVector.hh" #include "mem/ruby/system/System.hh" @@ -49,7 +48,6 @@ int RubySystem::m_memory_size_bits; Network* RubySystem::m_network_ptr; Profiler* RubySystem::m_profiler_ptr; -Tracer* RubySystem::m_tracer_ptr; MemoryVector* RubySystem::m_mem_vec_ptr; RubySystem::RubySystem(const Params *p) @@ -108,12 +106,6 @@ RubySystem::registerProfiler(Profiler* profiler_ptr) m_profiler_ptr = profiler_ptr; } -void -RubySystem::registerTracer(Tracer* tracer_ptr) -{ - m_tracer_ptr = tracer_ptr; -} - void RubySystem::registerAbstractController(AbstractController* cntrl) { @@ -124,7 +116,6 @@ RubySystem::~RubySystem() { delete m_network_ptr; delete m_profiler_ptr; - delete m_tracer_ptr; if (m_mem_vec_ptr) delete m_mem_vec_ptr; } diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index 704cc3b27..bcc62a518 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -48,7 +48,6 @@ class CacheRecorder; class MemoryVector; class Network; class Profiler; -class Tracer; class RubySystem : public SimObject { @@ -86,13 +85,6 @@ class RubySystem : public SimObject return m_profiler_ptr; } - static Tracer* - getTracer() - { - assert(m_tracer_ptr != NULL); - return m_tracer_ptr; - } - static MemoryVector* getMemoryVector() { @@ -119,7 +111,6 @@ class RubySystem : public SimObject void registerNetwork(Network*); void registerProfiler(Profiler*); - void registerTracer(Tracer*); void registerAbstractController(AbstractController*); private: @@ -145,7 +136,6 @@ class RubySystem : public SimObject public: static Profiler* m_profiler_ptr; - static Tracer* m_tracer_ptr; static MemoryVector* m_mem_vec_ptr; std::vector m_abs_cntrl_vec; }; -- cgit v1.2.3 From ab0347a1c66da6d491b127ec1aeb193f35f73019 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Wed, 11 Jan 2012 11:46:23 -0600 Subject: Ruby Memory Vector: Functions for collating and populating pages This patch adds functions to the memory vector class that can be used for collating memory pages to raw trace and for populating pages from a raw trace. --- src/mem/ruby/system/MemoryVector.hh | 86 ++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/mem/ruby/system/MemoryVector.hh b/src/mem/ruby/system/MemoryVector.hh index 6719b9fb6..9bd3516c2 100644 --- a/src/mem/ruby/system/MemoryVector.hh +++ b/src/mem/ruby/system/MemoryVector.hh @@ -29,6 +29,7 @@ #ifndef __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__ #define __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__ +#include "base/trace.hh" #include "mem/ruby/common/Address.hh" class DirectoryMemory; @@ -48,6 +49,8 @@ class MemoryVector void write(const Address & paddr, uint8* data, int len); uint8* read(const Address & paddr, uint8* data, int len); + uint32 collatePages(uint8* &raw_data); + void populatePages(uint8* raw_data); private: uint8* getBlockPtr(const PhysAddress & addr); @@ -56,6 +59,7 @@ class MemoryVector uint8** m_pages; uint32 m_num_pages; const uint32 m_page_offset_mask; + static const uint32 PAGE_SIZE = 4096; }; inline @@ -97,7 +101,7 @@ MemoryVector::resize(uint32 size) delete [] m_pages; } m_size = size; - assert(size%4096 == 0); + assert(size%PAGE_SIZE == 0); m_num_pages = size >> 12; m_pages = new uint8*[m_num_pages]; memset(m_pages, 0, m_num_pages * sizeof(uint8*)); @@ -118,8 +122,8 @@ MemoryVector::write(const Address & paddr, uint8* data, int len) } if (all_zeros) return; - m_pages[page_num] = new uint8[4096]; - memset(m_pages[page_num], 0, 4096); + m_pages[page_num] = new uint8[PAGE_SIZE]; + memset(m_pages[page_num], 0, PAGE_SIZE); uint32 offset = paddr.getAddress() & m_page_offset_mask; memcpy(&m_pages[page_num][offset], data, len); } else { @@ -147,10 +151,82 @@ MemoryVector::getBlockPtr(const PhysAddress & paddr) { uint32 page_num = paddr.getAddress() >> 12; if (m_pages[page_num] == 0) { - m_pages[page_num] = new uint8[4096]; - memset(m_pages[page_num], 0, 4096); + m_pages[page_num] = new uint8[PAGE_SIZE]; + memset(m_pages[page_num], 0, PAGE_SIZE); } return &m_pages[page_num][paddr.getAddress()&m_page_offset_mask]; } +/*! + * Function for collating all the pages of the physical memory together. + * In case a pointer for a page is NULL, this page needs only a single byte + * to represent that the pointer is NULL. Otherwise, it needs 1 + PAGE_SIZE + * bytes. The first represents that the page pointer is not NULL, and rest of + * the bytes represent the data on the page. + */ + +inline uint32 +MemoryVector::collatePages(uint8* &raw_data) +{ + uint32 num_zero_pages = 0; + uint32 data_size = 0; + + for (uint32 i = 0;i < m_num_pages; ++i) + { + if (m_pages[i] == 0) num_zero_pages++; + } + + raw_data = new uint8[ sizeof(uint32) /* number of pages*/ + + m_num_pages /* whether the page is all zeros */ + + PAGE_SIZE * (m_num_pages - num_zero_pages)]; + + /* Write the number of pages to be stored. */ + memcpy(raw_data, &m_num_pages, sizeof(uint32)); + data_size = sizeof(uint32); + + for (uint32 i = 0;i < m_num_pages; ++i) + { + if (m_pages[i] == 0) { + raw_data[data_size] = 0; + } else { + raw_data[data_size] = 1; + memcpy(raw_data + data_size + 1, m_pages[i], PAGE_SIZE); + data_size += PAGE_SIZE; + } + data_size += 1; + } + + return data_size; +} + +/*! + * Function for populating the pages of the memory using the available raw + * data. Each page has a byte associate with it, which represents whether the + * page was NULL or not, when all the pages were collated. The function assumes + * that the number of pages in the memory are same as those that were recorded + * in the checkpoint. + */ +inline void +MemoryVector::populatePages(uint8* raw_data) +{ + uint32 data_size = 0; + uint32 num_pages = 0; + + /* Read the number of pages that were stored. */ + memcpy(&num_pages, raw_data, sizeof(uint32)); + data_size = sizeof(uint32); + assert(num_pages == m_num_pages); + + for (uint32 i = 0;i < m_num_pages; ++i) + { + assert(m_pages[i] == 0); + if (raw_data[data_size] != 0) { + m_pages[i] = new uint8[PAGE_SIZE]; + memcpy(m_pages[i], raw_data + data_size + 1, PAGE_SIZE); + data_size += PAGE_SIZE; + } + data_size += 1; + } +} + #endif // __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__ -- cgit v1.2.3 From c3109f77757b08f74768d44983ff81d7d66819e7 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Wed, 11 Jan 2012 13:29:15 -0600 Subject: Ruby: Add infrastructure for recording cache contents This patch changes CacheRecorder, CacheMemory, CacheControllers so that the contents of a cache can be recorded for checkpointing purposes. --- src/mem/SConscript | 3 +- src/mem/ruby/recorder/CacheRecorder.cc | 156 ++++++++++++++++++--- src/mem/ruby/recorder/CacheRecorder.hh | 80 +++++++++-- src/mem/ruby/recorder/SConscript | 1 - src/mem/ruby/recorder/TraceRecord.cc | 139 ------------------ src/mem/ruby/recorder/TraceRecord.hh | 91 ------------ src/mem/ruby/slicc_interface/AbstractController.hh | 5 +- src/mem/ruby/system/CacheMemory.cc | 49 ++++--- src/mem/ruby/system/CacheMemory.hh | 16 +-- src/mem/slicc/symbols/StateMachine.py | 31 ++++ 10 files changed, 270 insertions(+), 301 deletions(-) delete mode 100644 src/mem/ruby/recorder/TraceRecord.cc delete mode 100644 src/mem/ruby/recorder/TraceRecord.hh (limited to 'src') diff --git a/src/mem/SConscript b/src/mem/SConscript index f4e4cc038..a0ba4d66a 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -62,6 +62,7 @@ DebugFlag('MemoryAccess') DebugFlag('ProtocolTrace') DebugFlag('RubyCache') +DebugFlag('RubyCacheTrace') DebugFlag('RubyDma') DebugFlag('RubyGenerated') DebugFlag('RubyMemory') @@ -75,4 +76,4 @@ DebugFlag('RubyTester') CompoundFlag('Ruby', [ 'RubyQueue', 'RubyNetwork', 'RubyTester', 'RubyGenerated', 'RubySlicc', 'RubyStorebuffer', 'RubyCache', - 'RubyMemory', 'RubyDma', 'RubyPort', 'RubySequencer']) + 'RubyMemory', 'RubyDma', 'RubyPort', 'RubySequencer', 'RubyCacheTrace']) diff --git a/src/mem/ruby/recorder/CacheRecorder.cc b/src/mem/ruby/recorder/CacheRecorder.cc index fc6ad0975..8b724859e 100644 --- a/src/mem/ruby/recorder/CacheRecorder.cc +++ b/src/mem/ruby/recorder/CacheRecorder.cc @@ -1,5 +1,6 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood + * Copyright (c) 2010 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,43 +27,154 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include - -#include "mem/ruby/eventqueue/RubyEventQueue.hh" +#include "debug/RubyCacheTrace.hh" #include "mem/ruby/recorder/CacheRecorder.hh" -#include "gzstream.hh" +#include "mem/ruby/system/Sequencer.hh" +#include "mem/ruby/system/System.hh" using namespace std; void -CacheRecorder::addRecord(Sequencer* sequencer, const Address& data_addr, - const Address& pc_addr, RubyRequestType type, Time time) +TraceRecord::print(ostream& out) const +{ + out << "[TraceRecord: Node, " << m_cntrl_id << ", " + << m_data_address << ", " << m_pc_address << ", " + << m_type << ", Time: " << m_time << "]"; +} + +CacheRecorder::CacheRecorder() + : m_uncompressed_trace(NULL), + m_uncompressed_trace_size(0) { - TraceRecord rec(sequencer, data_addr, pc_addr, type, time); - m_records.push_back(rec); } -int -CacheRecorder::dumpRecords(string filename) +CacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, + uint64_t uncompressed_trace_size, + std::vector& seq_map) + : m_uncompressed_trace(uncompressed_trace), + m_uncompressed_trace_size(uncompressed_trace_size), + m_seq_map(seq_map), m_bytes_read(0), m_records_read(0), + m_records_flushed(0) { - ogzstream out(filename.c_str()); - if (out.fail()) { - cout << "Error: error opening file '" << filename << "'" << endl; - return 0; +} + +CacheRecorder::~CacheRecorder() +{ + if (m_uncompressed_trace != NULL) { + delete m_uncompressed_trace; + m_uncompressed_trace = NULL; } + m_seq_map.clear(); +} - std::sort(m_records.begin(), m_records.end(), greater()); +void +CacheRecorder::enqueueNextFlushRequest() +{ + if (m_records_flushed < m_records.size()) { + TraceRecord* rec = m_records[m_records_flushed]; + m_records_flushed++; + Request* req = new Request(rec->m_data_address, + RubySystem::getBlockSizeBytes(),0); + MemCmd::Command requestType = MemCmd::FlushReq; + Packet *pkt = new Packet(req, requestType, -1); - int size = m_records.size(); - for (int i = 0; i < size; ++i) - m_records[i].output(out); + Sequencer* m_sequencer_ptr = m_seq_map[rec->m_cntrl_id]; + assert(m_sequencer_ptr != NULL); + m_sequencer_ptr->makeRequest(pkt); - m_records.clear(); + DPRINTF(RubyCacheTrace, "Flushing %s\n", *rec); + } +} + +void +CacheRecorder::enqueueNextFetchRequest() +{ + if (m_bytes_read < m_uncompressed_trace_size) { + TraceRecord* traceRecord = (TraceRecord*) (m_uncompressed_trace + + m_bytes_read); - return size; + DPRINTF(RubyCacheTrace, "Issuing %s\n", *traceRecord); + Request* req = new Request(); + MemCmd::Command requestType; + + if (traceRecord->m_type == RubyRequestType_LD) { + requestType = MemCmd::ReadReq; + req->setPhys(traceRecord->m_data_address, + RubySystem::getBlockSizeBytes(),0); + } else if (traceRecord->m_type == RubyRequestType_IFETCH) { + requestType = MemCmd::ReadReq; + req->setPhys(traceRecord->m_data_address, + RubySystem::getBlockSizeBytes(), + Request::INST_FETCH); + } else { + requestType = MemCmd::WriteReq; + req->setPhys(traceRecord->m_data_address, + RubySystem::getBlockSizeBytes(),0); + } + + Packet *pkt = new Packet(req, requestType, -1); + pkt->dataStatic(traceRecord->m_data); + + Sequencer* m_sequencer_ptr = m_seq_map[traceRecord->m_cntrl_id]; + assert(m_sequencer_ptr != NULL); + m_sequencer_ptr->makeRequest(pkt); + + m_bytes_read += (sizeof(TraceRecord) + + RubySystem::getBlockSizeBytes()); + m_records_read++; + } } void -CacheRecorder::print(ostream& out) const +CacheRecorder::addRecord(int cntrl, const physical_address_t data_addr, + const physical_address_t pc_addr, + RubyRequestType type, Time time, DataBlock& data) +{ + TraceRecord* rec = (TraceRecord*)malloc(sizeof(TraceRecord) + + RubySystem::getBlockSizeBytes()); + rec->m_cntrl_id = cntrl; + rec->m_time = time; + rec->m_data_address = data_addr; + rec->m_pc_address = pc_addr; + rec->m_type = type; + memcpy(rec->m_data, data.getData(0, RubySystem::getBlockSizeBytes()), + RubySystem::getBlockSizeBytes()); + + m_records.push_back(rec); +} + +uint64 +CacheRecorder::aggregateRecords(uint8_t** buf, uint64 total_size) { + std::sort(m_records.begin(), m_records.end(), compareTraceRecords); + + int size = m_records.size(); + uint64 current_size = 0; + int record_size = sizeof(TraceRecord) + RubySystem::getBlockSizeBytes(); + + for (int i = 0; i < size; ++i) { + // Determine if we need to expand the buffer size + if (current_size + record_size > total_size) { + uint8_t* new_buf = new (nothrow) uint8_t[total_size * 2]; + if (new_buf == NULL) { + fatal("Unable to allocate buffer of size %s\n", + total_size * 2); + } + total_size = total_size * 2; + uint8_t* old_buf = *buf; + memcpy(new_buf, old_buf, current_size); + *buf = new_buf; + delete [] old_buf; + } + + // Copy the current record into the buffer + memcpy(&((*buf)[current_size]), m_records[i], record_size); + current_size += record_size; + + free(m_records[i]); + m_records[i] = NULL; + } + + m_records.clear(); + return current_size; } diff --git a/src/mem/ruby/recorder/CacheRecorder.hh b/src/mem/ruby/recorder/CacheRecorder.hh index 9f96f4fa0..839c4f6b1 100644 --- a/src/mem/ruby/recorder/CacheRecorder.hh +++ b/src/mem/ruby/recorder/CacheRecorder.hh @@ -1,5 +1,6 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood + * Copyright (c) 2010 Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,37 +35,90 @@ #ifndef __MEM_RUBY_RECORDER_CACHERECORDER_HH__ #define __MEM_RUBY_RECORDER_CACHERECORDER_HH__ -#include -#include #include +#include "base/hashmap.hh" #include "mem/protocol/RubyRequestType.hh" -#include "mem/ruby/common/Global.hh" -#include "mem/ruby/recorder/TraceRecord.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/common/DataBlock.hh" +#include "mem/ruby/common/TypeDefines.hh" -class Address; -class TraceRecord; class Sequencer; +/*! + * Class for recording cache contents. Note that the last element of the + * class is an array of length zero. It is used for creating variable + * length object, so that while writing the data to a file one does not + * need to copy the meta data and the actual data separately. + */ +class TraceRecord { + public: + int m_cntrl_id; + Time m_time; + physical_address_t m_data_address; + physical_address_t m_pc_address; + RubyRequestType m_type; + uint8_t m_data[0]; + + void print(std::ostream& out) const; +}; + class CacheRecorder { public: - void addRecord(Sequencer* sequencer, const Address& data_addr, - const Address& pc_addr, RubyRequestType type, Time time); - int dumpRecords(std::string filename); + CacheRecorder(); + ~CacheRecorder(); - void print(std::ostream& out) const; + CacheRecorder(uint8_t* uncompressed_trace, + uint64_t uncompressed_trace_size, + std::vector& SequencerMap); + void addRecord(int cntrl, const physical_address_t data_addr, + const physical_address_t pc_addr, RubyRequestType type, + Time time, DataBlock& data); + + uint64 aggregateRecords(uint8_t** data, uint64 size); + + /*! + * Function for flushing the memory contents of the caches to the + * main memory. It goes through the recorded contents of the caches, + * and issues flush requests. Except for the first one, a flush request + * is issued only after the previous one has completed. This currently + * requires use of MOESI Hammer protocol since only that protocol + * supports flush requests. + */ + void enqueueNextFlushRequest(); + + /*! + * Function for fetching warming up the memory and the caches. It goes + * through the recorded contents of the caches, as available in the + * checkpoint and issues fetch requests. Except for the first one, a + * fetch request is issued only after the previous one has completed. + * It should be possible to use this with any protocol. + */ + void enqueueNextFetchRequest(); private: // Private copy constructor and assignment operator CacheRecorder(const CacheRecorder& obj); CacheRecorder& operator=(const CacheRecorder& obj); - std::vector m_records; + std::vector m_records; + uint8_t* m_uncompressed_trace; + uint64_t m_uncompressed_trace_size; + std::vector m_seq_map; + uint64_t m_bytes_read; + uint64_t m_records_read; + uint64_t m_records_flushed; }; +inline bool +compareTraceRecords(const TraceRecord* n1, const TraceRecord* n2) +{ + return n1->m_time > n2->m_time; +} + inline std::ostream& -operator<<(std::ostream& out, const CacheRecorder& obj) +operator<<(std::ostream& out, const TraceRecord& obj) { obj.print(out); out << std::flush; diff --git a/src/mem/ruby/recorder/SConscript b/src/mem/ruby/recorder/SConscript index 4258d2c47..e1b3d78b7 100644 --- a/src/mem/ruby/recorder/SConscript +++ b/src/mem/ruby/recorder/SConscript @@ -34,4 +34,3 @@ if env['PROTOCOL'] == 'None': Return() Source('CacheRecorder.cc') -Source('TraceRecord.cc', Werror=False) diff --git a/src/mem/ruby/recorder/TraceRecord.cc b/src/mem/ruby/recorder/TraceRecord.cc deleted file mode 100644 index 79186d33b..000000000 --- a/src/mem/ruby/recorder/TraceRecord.cc +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * 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. - */ - -#include "mem/protocol/RubyRequest.hh" -#include "mem/ruby/recorder/TraceRecord.hh" -#include "mem/ruby/system/Sequencer.hh" -#include "mem/ruby/system/System.hh" -#include "sim/sim_object.hh" - -using namespace std; - -TraceRecord::TraceRecord(Sequencer* _sequencer, const Address& data_addr, - const Address& pc_addr, RubyRequestType type, Time time) -{ - m_sequencer_ptr = _sequencer; - m_data_address = data_addr; - m_pc_address = pc_addr; - m_time = time; - m_type = type; - - // Don't differentiate between store misses and atomic requests in - // the trace - if (m_type == RubyRequestType_Load_Linked) { - m_type = RubyRequestType_ST; - } else if (m_type == RubyRequestType_Store_Conditional) { - m_type = RubyRequestType_ST; - } -} - -TraceRecord::TraceRecord(const TraceRecord& obj) -{ - // Call assignment operator - *this = obj; -} - -TraceRecord& -TraceRecord::operator=(const TraceRecord& obj) -{ - m_sequencer_ptr = obj.m_sequencer_ptr; - m_time = obj.m_time; - m_data_address = obj.m_data_address; - m_pc_address = obj.m_pc_address; - m_type = obj.m_type; - return *this; -} - -void -TraceRecord::issueRequest() const -{ - assert(m_sequencer_ptr != NULL); - Request req(m_data_address.getAddress(), 0, 0); - Packet *pkt = new Packet(&req, MemCmd(MemCmd::InvalidCmd), -1); - - // Clear out the sequencer - while (!m_sequencer_ptr->empty()) { - g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 100); - } - - m_sequencer_ptr->makeRequest(pkt); - - // Clear out the sequencer - while (!m_sequencer_ptr->empty()) { - g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 100); - } -} - -void -TraceRecord::print(ostream& out) const -{ - out << "[TraceRecord: Node, " << m_sequencer_ptr->name() << ", " - << m_data_address << ", " << m_pc_address << ", " - << m_type << ", Time: " << m_time << "]"; -} - -void -TraceRecord::output(ostream& out) const -{ - out << m_sequencer_ptr->name() << " "; - m_data_address.output(out); - out << " "; - m_pc_address.output(out); - out << " "; - out << m_type; - out << endl; -} - -bool -TraceRecord::input(istream& in) -{ - string sequencer_name; - in >> sequencer_name; - - // The SimObject find function is slow and iterates through the - // simObjectList to find the sequencer pointer. Therefore, expect - // trace playback to be slow. - m_sequencer_ptr = (Sequencer*)SimObject::find(sequencer_name.c_str()); - - m_data_address.input(in); - m_pc_address.input(in); - if (in.eof()) - return false; - - string type; - in >> type; - m_type = string_to_RubyRequestType(type); - - // Ignore the rest of the line - char c = '\0'; - while ((!in.eof()) && (c != '\n')) { - in.get(c); - } - - return true; -} diff --git a/src/mem/ruby/recorder/TraceRecord.hh b/src/mem/ruby/recorder/TraceRecord.hh deleted file mode 100644 index 42f213564..000000000 --- a/src/mem/ruby/recorder/TraceRecord.hh +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * 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. - */ - -/* - * A entry in the cache request record. It is aware of the ruby time - * and can issue the request back to the cache. - */ - -#ifndef __MEM_RUBY_RECORDER_TRACERECORD_HH__ -#define __MEM_RUBY_RECORDER_TRACERECORD_HH__ - -#include - -#include "mem/ruby/common/Address.hh" -#include "mem/ruby/common/Global.hh" -#include "mem/ruby/system/Sequencer.hh" - -class CacheMsg; - -class TraceRecord -{ - public: - TraceRecord(Sequencer* _sequencer, const Address& data_addr, - const Address& pc_addr, RubyRequestType type, Time time); - - TraceRecord() - { - m_sequencer_ptr = NULL; - m_time = 0; - m_type = RubyRequestType_NULL; - } - - TraceRecord(const TraceRecord& obj); - TraceRecord& operator=(const TraceRecord& obj); - - void issueRequest() const; - - void print(std::ostream& out) const; - void output(std::ostream& out) const; - bool input(std::istream& in); - - private: - friend bool operator>(const TraceRecord& n1, const TraceRecord& n2); - - Sequencer* m_sequencer_ptr; - Time m_time; - Address m_data_address; - Address m_pc_address; - RubyRequestType m_type; -}; - -inline bool -operator>(const TraceRecord& n1, const TraceRecord& n2) -{ - return n1.m_time > n2.m_time; -} - -inline std::ostream& -operator<<(std::ostream& out, const TraceRecord& obj) -{ - obj.print(out); - out << std::flush; - return out; -} - -#endif // __MEM_RUBY_RECORDER_TRACERECORD_HH__ diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index ca37a90de..a0e3b3fbb 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -33,12 +33,11 @@ #include #include "mem/protocol/AccessPermission.hh" -#include "mem/protocol/MachineType.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Consumer.hh" #include "mem/ruby/common/DataBlock.hh" #include "mem/ruby/network/Network.hh" -#include "mem/ruby/system/System.hh" +#include "mem/ruby/recorder/CacheRecorder.hh" #include "params/RubyController.hh" #include "sim/sim_object.hh" @@ -68,6 +67,8 @@ class AbstractController : public SimObject, public Consumer virtual void wakeup() = 0; // virtual void dumpStats(std::ostream & out) = 0; virtual void clearStats() = 0; + virtual void recordCacheTrace(int cntrl, CacheRecorder* tr) = 0; + virtual Sequencer* getSequencer() const = 0; }; #endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__ diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc index 1564128d3..9f1fe6320 100644 --- a/src/mem/ruby/system/CacheMemory.cc +++ b/src/mem/ruby/system/CacheMemory.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,9 @@ #include "base/intmath.hh" #include "debug/RubyCache.hh" +#include "mem/protocol/AccessPermission.hh" #include "mem/ruby/system/CacheMemory.hh" +#include "mem/ruby/system/System.hh" using namespace std; @@ -364,31 +366,42 @@ CacheMemory::profileGenericRequest(GenericRequestType requestType, } void -CacheMemory::recordCacheContents(CacheRecorder& tr) const +CacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const { + uint64 warmedUpBlocks = 0; + uint64 totalBlocks M5_VAR_USED = (uint64)m_cache_num_sets + * (uint64)m_cache_assoc; + for (int i = 0; i < m_cache_num_sets; i++) { for (int j = 0; j < m_cache_assoc; j++) { - AccessPermission perm = m_cache[i][j]->m_Permission; - RubyRequestType request_type = RubyRequestType_NULL; - if (perm == AccessPermission_Read_Only) { - if (m_is_instruction_only_cache) { - request_type = RubyRequestType_IFETCH; - } else { - request_type = RubyRequestType_LD; + if (m_cache[i][j] != NULL) { + AccessPermission perm = m_cache[i][j]->m_Permission; + RubyRequestType request_type = RubyRequestType_NULL; + if (perm == AccessPermission_Read_Only) { + if (m_is_instruction_only_cache) { + request_type = RubyRequestType_IFETCH; + } else { + request_type = RubyRequestType_LD; + } + } else if (perm == AccessPermission_Read_Write) { + request_type = RubyRequestType_ST; } - } else if (perm == AccessPermission_Read_Write) { - request_type = RubyRequestType_ST; - } - if (request_type != RubyRequestType_NULL) { -#if 0 - tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, - Address(0), request_type, - m_replacementPolicy_ptr->getLastAccess(i, j)); -#endif + if (request_type != RubyRequestType_NULL) { + tr->addRecord(cntrl, m_cache[i][j]->m_Address.getAddress(), + 0, request_type, + m_replacementPolicy_ptr->getLastAccess(i, j), + m_cache[i][j]->getDataBlk()); + warmedUpBlocks++; + } } } } + + DPRINTF(RubyCache, "%s: %lli blocks of %lli total blocks" + "recorded %.2f%% \n", name().c_str(), warmedUpBlocks, + (uint64)m_cache_num_sets * (uint64)m_cache_assoc, + (float(warmedUpBlocks)/float(totalBlocks))*100.0); } void diff --git a/src/mem/ruby/system/CacheMemory.hh b/src/mem/ruby/system/CacheMemory.hh index f0acba9cb..f270e88cd 100644 --- a/src/mem/ruby/system/CacheMemory.hh +++ b/src/mem/ruby/system/CacheMemory.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,21 +34,15 @@ #include #include "base/hashmap.hh" -#include "mem/protocol/AccessPermission.hh" #include "mem/protocol/GenericRequestType.hh" #include "mem/protocol/RubyRequest.hh" -#include "mem/protocol/RubyRequestType.hh" -#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/DataBlock.hh" -#include "mem/ruby/common/Global.hh" #include "mem/ruby/profiler/CacheProfiler.hh" #include "mem/ruby/recorder/CacheRecorder.hh" #include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" -#include "mem/ruby/slicc_interface/AbstractController.hh" #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" #include "mem/ruby/system/LRUPolicy.hh" #include "mem/ruby/system/PseudoLRUPolicy.hh" -#include "mem/ruby/system/System.hh" #include "params/RubyCache.hh" #include "sim/sim_object.hh" @@ -100,12 +94,7 @@ class CacheMemory : public SimObject int getLatency() const { return m_latency; } // Hook for checkpointing the contents of the cache - void recordCacheContents(CacheRecorder& tr) const; - void - setAsInstructionCache(bool is_icache) - { - m_is_instruction_only_cache = is_icache; - } + void recordCacheContents(int cntrl, CacheRecorder* tr) const; // Set this address to most recently used void setMRU(const Address& address); @@ -146,7 +135,6 @@ class CacheMemory : public SimObject // Data Members (m_prefix) bool m_is_instruction_only_cache; - bool m_is_data_only_cache; // The first index is the # of cache lines. // The second index is the the amount associativity. diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index a3ea1ca8a..85df3f9e8 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -264,6 +264,8 @@ public: void clearStats(); void blockOnQueue(Address addr, MessageBuffer* port); void unblock(Address addr); + void recordCacheTrace(int cntrl, CacheRecorder* tr); + Sequencer* getSequencer() const; private: ''') @@ -674,6 +676,12 @@ $vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{v else: mq_ident = "NULL" + seq_ident = "NULL" + for param in self.config_parameters: + if param.name == "sequencer": + assert(param.pointer) + seq_ident = "m_%s_ptr" % param.name + code(''' int $c_ident::getNumControllers() @@ -687,6 +695,12 @@ $c_ident::getMandatoryQueue() const return $mq_ident; } +Sequencer* +$c_ident::getSequencer() const +{ + return $seq_ident; +} + const int & $c_ident::getVersion() const { @@ -875,6 +889,23 @@ $c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) code(''' +void +$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) +{ +''') + # + # Record cache contents for all associated caches. + # + code.indent() + for param in self.config_parameters: + if param.type_ast.type.ident == "CacheMemory": + assert(param.pointer) + code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') + + code.dedent() + code(''' +} + // Actions ''') if self.TBEType != None and self.EntryType != None: -- cgit v1.2.3 From 8b3ad17cc3189ed7470c82e9108669fe48541f43 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Wed, 11 Jan 2012 13:29:54 -0600 Subject: Ruby Sparse Memory: Add function for collating blocks This patch adds function to the Sparse Memory so that the blocks can be recorded in a cache trace. The blocks are added to the cache recorder which can later write them into a file. --- src/mem/ruby/system/SparseMemory.cc | 67 +++++++++++++++++++++++++++++++++++++ src/mem/ruby/system/SparseMemory.hh | 13 +++++-- 2 files changed, 78 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mem/ruby/system/SparseMemory.cc b/src/mem/ruby/system/SparseMemory.cc index 0cfd0d90c..db8d494f8 100644 --- a/src/mem/ruby/system/SparseMemory.cc +++ b/src/mem/ruby/system/SparseMemory.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2009 Advanced Micro Devices, Inc. + * Copyright (c) 2012 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,6 +27,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include + #include "debug/RubyCache.hh" #include "mem/ruby/system/SparseMemory.hh" #include "mem/ruby/system/System.hh" @@ -341,6 +344,70 @@ SparseMemory::lookup(const Address& address) return entry; } +void +SparseMemory::recordBlocks(int cntrl_id, CacheRecorder* tr) const +{ + queue unexplored_nodes[2]; + queue address_of_nodes[2]; + + unexplored_nodes[0].push(m_map_head); + address_of_nodes[0].push(0); + + int parity_of_level = 0; + physical_address_t address, temp_address; + Address curAddress; + + // Initiallize the high bit to be the total number of bits plus + // the block offset. However the highest bit index is one less + // than this value. + int highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits(); + int lowBit; + + for (int cur_level = 0; cur_level < m_number_of_levels; cur_level++) { + + // create the appropriate address for this level + // Note: that set Address is inclusive of the specified range, + // thus the high bit is one less than the total number of bits + // used to create the address. + lowBit = highBit - m_number_of_bits_per_level[cur_level]; + + while (!unexplored_nodes[parity_of_level].empty()) { + + SparseMapType* node = unexplored_nodes[parity_of_level].front(); + unexplored_nodes[parity_of_level].pop(); + + address = address_of_nodes[parity_of_level].front(); + address_of_nodes[parity_of_level].pop(); + + SparseMapType::iterator iter; + + for (iter = node->begin(); iter != node->end(); iter++) { + SparseMemEntry entry = (*iter).second; + curAddress = (*iter).first; + + if (cur_level != (m_number_of_levels - 1)) { + // If not at the last level, put this node in the queue + unexplored_nodes[1 - parity_of_level].push( + (SparseMapType*)(entry)); + address_of_nodes[1 - parity_of_level].push(address | + (curAddress.getAddress() << lowBit)); + } else { + // If at the last level, add a trace record + temp_address = address | (curAddress.getAddress() + << lowBit); + DataBlock block = ((AbstractEntry*)entry)->getDataBlk(); + tr->addRecord(cntrl_id, temp_address, 0, RubyRequestType_ST, 0, + block); + } + } + } + + // Adjust the highBit value for the next level + highBit -= m_number_of_bits_per_level[cur_level]; + parity_of_level = 1 - parity_of_level; + } +} + void SparseMemory::print(ostream& out) const { diff --git a/src/mem/ruby/system/SparseMemory.hh b/src/mem/ruby/system/SparseMemory.hh index f4cc12f97..e4237dbcd 100644 --- a/src/mem/ruby/system/SparseMemory.hh +++ b/src/mem/ruby/system/SparseMemory.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2009 Advanced Micro Devices, Inc. + * Copyright (c) 2012 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,9 +33,9 @@ #include #include "base/hashmap.hh" -#include "mem/ruby/slicc_interface/AbstractEntry.hh" #include "mem/ruby/common/Address.hh" -#include "mem/ruby/common/Global.hh" +#include "mem/ruby/recorder/CacheRecorder.hh" +#include "mem/ruby/slicc_interface/AbstractEntry.hh" typedef void* SparseMemEntry; typedef m5::hash_map SparseMapType; @@ -59,6 +60,14 @@ class SparseMemory void add(const Address& address, AbstractEntry*); void remove(const Address& address); + /*! + * Function for recording the contents of memory. This function walks + * through all the levels of the sparse memory in a breadth first + * fashion. This might need more memory than a depth first approach. + * But breadth first seems easier to me than a depth first approach. + */ + void recordBlocks(int cntrl_id, CacheRecorder *) const; + AbstractEntry* lookup(const Address& address); // Print cache contents -- cgit v1.2.3 From 17fc60ee88cf6cc6d0e703e04a90951f77cf48da Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Wed, 11 Jan 2012 13:31:04 -0600 Subject: Ruby EventQueue: Remove unused functions --- src/mem/ruby/eventqueue/RubyEventQueue.hh | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/mem/ruby/eventqueue/RubyEventQueue.hh b/src/mem/ruby/eventqueue/RubyEventQueue.hh index 20b44362a..67fe6131b 100644 --- a/src/mem/ruby/eventqueue/RubyEventQueue.hh +++ b/src/mem/ruby/eventqueue/RubyEventQueue.hh @@ -58,7 +58,6 @@ #include -#include "config/no_vector_bounds_checks.hh" #include "mem/ruby/common/TypeDefines.hh" #include "sim/eventq.hh" @@ -77,9 +76,6 @@ class RubyEventQueue : public EventManager void scheduleEventAbsolute(Consumer* consumer, Time timeAbs); void print(std::ostream& out) const; - void triggerEvents(Time t) { assert(0); } - void triggerAllEvents() { assert(0); } - private: // Private copy constructor and assignment operator RubyEventQueue(const RubyEventQueue& obj); -- cgit v1.2.3 From 2d3cae02f5d4a6c1f116f922d0ee3dde9e9dcc77 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Wed, 11 Jan 2012 13:39:58 -0600 Subject: Ruby Port: Add a list of cpu ports attached to this port --- src/mem/ruby/system/RubyPort.cc | 6 ++++-- src/mem/ruby/system/RubyPort.hh | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index f7bde739e..d5f21c312 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -66,8 +66,10 @@ Port * RubyPort::getPort(const std::string &if_name, int idx) { if (if_name == "port") { - return new M5Port(csprintf("%s-port%d", name(), idx), this, - ruby_system, access_phys_mem); + M5Port* cpuPort = new M5Port(csprintf("%s-port%d", name(), idx), + this, ruby_system, access_phys_mem); + cpu_ports.push_back(cpuPort); + return cpuPort; } if (if_name == "pio_port") { diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index 88e865766..0160d8fc8 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -148,6 +148,10 @@ class RubyPort : public MemObject M5Port* physMemPort; + /*! Vector of CPU Port attached to this Ruby port. */ + typedef std::vector::iterator CpuPortIter; + std::vector cpu_ports; + PhysicalMemory* physmem; RubySystem* ruby_system; -- cgit v1.2.3 From 3f8065290a4740baea8b9a8ebcd361b161636d56 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Wed, 11 Jan 2012 13:42:00 -0600 Subject: Ruby Debug Flags: Remove one, add another The flag RubyStoreBuffer is being removed, instead RubySystem is being added --- src/mem/SConscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mem/SConscript b/src/mem/SConscript index a0ba4d66a..50423fa67 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -71,9 +71,9 @@ DebugFlag('RubyPort') DebugFlag('RubyQueue') DebugFlag('RubySequencer') DebugFlag('RubySlicc') -DebugFlag('RubyStorebuffer') +DebugFlag('RubySystem') DebugFlag('RubyTester') CompoundFlag('Ruby', [ 'RubyQueue', 'RubyNetwork', 'RubyTester', - 'RubyGenerated', 'RubySlicc', 'RubyStorebuffer', 'RubyCache', + 'RubyGenerated', 'RubySlicc', 'RubySystem', 'RubyCache', 'RubyMemory', 'RubyDma', 'RubyPort', 'RubySequencer', 'RubyCacheTrace']) -- cgit v1.2.3 From bf59a9298f6154cb85ebebabd4f45738caf29b35 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Wed, 11 Jan 2012 13:48:48 -0600 Subject: Ruby: Resurrect Cache Warmup Capability This patch resurrects ruby's cache warmup capability. It essentially makes use of all the infrastructure that was added to the controllers, memories and the cache recorder. --- src/mem/ruby/buffers/MessageBuffer.cc | 6 +- src/mem/ruby/system/DMASequencer.hh | 3 + src/mem/ruby/system/DirectoryMemory.cc | 1 + src/mem/ruby/system/RubyPort.cc | 80 ++++++++++- src/mem/ruby/system/RubyPort.hh | 11 +- src/mem/ruby/system/Sequencer.cc | 17 ++- src/mem/ruby/system/Sequencer.hh | 14 +- src/mem/ruby/system/System.cc | 239 +++++++++++++++++++++++++++++++-- src/mem/ruby/system/System.hh | 42 ++++-- 9 files changed, 389 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/mem/ruby/buffers/MessageBuffer.cc b/src/mem/ruby/buffers/MessageBuffer.cc index cab98cee9..9a7fdb61b 100644 --- a/src/mem/ruby/buffers/MessageBuffer.cc +++ b/src/mem/ruby/buffers/MessageBuffer.cc @@ -198,7 +198,11 @@ MessageBuffer::enqueue(MsgPtr message, Time delta) m_last_arrival_time * g_eventQueue_ptr->getClock()); } } - m_last_arrival_time = arrival_time; + + // If running a cache trace, don't worry about the last arrival checks + if (!g_system_ptr->m_warmup_enabled) { + m_last_arrival_time = arrival_time; + } // compute the delay cycles and set enqueue time Message* msg_ptr = message.get(); diff --git a/src/mem/ruby/system/DMASequencer.hh b/src/mem/ruby/system/DMASequencer.hh index 5f6b9f100..099c1d991 100644 --- a/src/mem/ruby/system/DMASequencer.hh +++ b/src/mem/ruby/system/DMASequencer.hh @@ -55,6 +55,9 @@ class DMASequencer : public RubyPort /* external interface */ RequestStatus makeRequest(PacketPtr pkt); bool busy() { return m_is_busy;} + int outstandingCount() const { return (m_is_busy ? 1 : 0); } + bool isDeadlockEventScheduled() const { return false; } + void descheduleDeadlockEvent() {} /* SLICC callback */ void dataCallback(const DataBlock & dblk); diff --git a/src/mem/ruby/system/DirectoryMemory.cc b/src/mem/ruby/system/DirectoryMemory.cc index 03aa68919..d2e00ab3b 100644 --- a/src/mem/ruby/system/DirectoryMemory.cc +++ b/src/mem/ruby/system/DirectoryMemory.cc @@ -58,6 +58,7 @@ DirectoryMemory::init() if (m_use_map) { m_sparseMemory = new SparseMemory(m_map_levels); + g_system_ptr->registerSparseMemory(m_sparseMemory); } else { m_entries = new AbstractEntry*[m_num_entries]; for (int i = 0; i < m_num_entries; i++) diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index d5f21c312..64faf6aed 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -27,11 +27,11 @@ */ #include "cpu/testers/rubytest/RubyTester.hh" +#include "debug/Config.hh" #include "debug/Ruby.hh" #include "mem/protocol/AccessPermission.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" #include "mem/ruby/system/RubyPort.hh" -#include "mem/physical.hh" RubyPort::RubyPort(const Params *p) : MemObject(p) @@ -51,6 +51,8 @@ RubyPort::RubyPort(const Params *p) m_usingRubyTester = p->using_ruby_tester; access_phys_mem = p->access_phys_mem; + drainEvent = NULL; + ruby_system = p->ruby_system; waitingOnSequencer = false; } @@ -510,6 +512,82 @@ RubyPort::ruby_hit_callback(PacketPtr pkt) (*i)->sendRetry(); } } + + testDrainComplete(); +} + +void +RubyPort::testDrainComplete() +{ + //If we weren't able to drain before, we might be able to now. + if (drainEvent != NULL) { + unsigned int drainCount = getDrainCount(drainEvent); + DPRINTF(Config, "Drain count: %u\n", drainCount); + if (drainCount == 0) { + drainEvent->process(); + // Clear the drain event once we're done with it. + drainEvent = NULL; + } + } +} + +unsigned int +RubyPort::getDrainCount(Event *de) +{ + int count = 0; + // + // If the sequencer is not empty, then requests need to drain. + // The outstandingCount is the number of requests outstanding and thus the + // number of times M5's timing port will process the drain event. + // + count += outstandingCount(); + + DPRINTF(Config, "outstanding count %d\n", outstandingCount()); + + // To simplify the draining process, the sequencer's deadlock detection + // event should have been descheduled. + assert(isDeadlockEventScheduled() == false); + + if (pio_port != NULL) { + count += pio_port->drain(de); + DPRINTF(Config, "count after pio check %d\n", count); + } + if (physMemPort != NULL) { + count += physMemPort->drain(de); + DPRINTF(Config, "count after physmem check %d\n", count); + } + + for (CpuPortIter p_iter = cpu_ports.begin(); p_iter != cpu_ports.end(); + p_iter++) { + M5Port* cpu_port = *p_iter; + count += cpu_port->drain(de); + DPRINTF(Config, "count after cpu port check %d\n", count); + } + + DPRINTF(Config, "final count %d\n", count); + + return count; +} + +unsigned int +RubyPort::drain(Event *de) +{ + if (isDeadlockEventScheduled()) { + descheduleDeadlockEvent(); + } + + int count = getDrainCount(de); + + // Set status + if (count != 0) { + drainEvent = de; + + changeState(SimObject::Draining); + return count; + } + + changeState(SimObject::Drained); + return 0; } void diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index 0160d8fc8..d8dbe0cda 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -33,7 +33,6 @@ #include #include "mem/protocol/RequestStatus.hh" -#include "mem/ruby/slicc_interface/RubyRequest.hh" #include "mem/ruby/system/System.hh" #include "mem/mem_object.hh" #include "mem/physical.hh" @@ -115,17 +114,23 @@ class RubyPort : public MemObject Port *getPort(const std::string &if_name, int idx); virtual RequestStatus makeRequest(PacketPtr pkt) = 0; + virtual int outstandingCount() const = 0; + virtual bool isDeadlockEventScheduled() const = 0; + virtual void descheduleDeadlockEvent() = 0; // // Called by the controller to give the sequencer a pointer. // A pointer to the controller is needed for atomic support. // void setController(AbstractController* _cntrl) { m_controller = _cntrl; } + int getId() { return m_version; } + unsigned int drain(Event *de); protected: const std::string m_name; void ruby_hit_callback(PacketPtr pkt); void hit(PacketPtr pkt); + void testDrainComplete(); int m_version; AbstractController* m_controller; @@ -143,6 +148,8 @@ class RubyPort : public MemObject } } + unsigned int getDrainCount(Event *de); + uint16_t m_port_id; uint64_t m_request_cnt; @@ -152,6 +159,8 @@ class RubyPort : public MemObject typedef std::vector::iterator CpuPortIter; std::vector cpu_ports; + Event *drainEvent; + PhysicalMemory* physmem; RubySystem* ruby_system; diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index f489e3461..3f9ceb34d 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -519,7 +519,11 @@ Sequencer::hitCallback(SequencerRequest* srequest, } // update the data - if (pkt->getPtr(true) != NULL) { + if (g_system_ptr->m_warmup_enabled) { + assert(pkt->getPtr(false) != NULL); + data.setData(pkt->getPtr(false), + request_address.getOffset(), pkt->getSize()); + } else if (pkt->getPtr(true) != NULL) { if ((type == RubyRequestType_LD) || (type == RubyRequestType_IFETCH) || (type == RubyRequestType_RMW_Read) || @@ -551,8 +555,17 @@ Sequencer::hitCallback(SequencerRequest* srequest, testerSenderState->subBlock->mergeFrom(data); } - ruby_hit_callback(pkt); delete srequest; + + if (g_system_ptr->m_warmup_enabled) { + delete pkt; + g_system_ptr->m_cache_recorder->enqueueNextFetchRequest(); + } else if (g_system_ptr->m_cooldown_enabled) { + delete pkt; + g_system_ptr->m_cache_recorder->enqueueNextFlushRequest(); + } else { + ruby_hit_callback(pkt); + } } bool diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index 7c2d0af13..4a6d46c01 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -39,8 +39,6 @@ #include "mem/ruby/system/RubyPort.hh" class DataBlock; -class CacheMsg; -class MachineID; class CacheMemory; class RubySequencerParams; @@ -100,6 +98,18 @@ class Sequencer : public RubyPort, public Consumer RequestStatus makeRequest(PacketPtr pkt); bool empty() const; + int outstandingCount() const { return m_outstanding_count; } + bool + isDeadlockEventScheduled() const + { + return deadlockCheckEvent.scheduled(); + } + + void + descheduleDeadlockEvent() + { + deschedule(deadlockCheckEvent); + } void print(std::ostream& out) const; void printStats(std::ostream& out) const; diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc index abba4eedc..6f191819b 100644 --- a/src/mem/ruby/system/System.cc +++ b/src/mem/ruby/system/System.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 1999-2011 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,15 +26,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include + +#include + #include "base/intmath.hh" #include "base/output.hh" -#include "mem/ruby/buffers/MessageBuffer.hh" +#include "debug/RubySystem.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/network/Network.hh" #include "mem/ruby/profiler/Profiler.hh" -#include "mem/ruby/slicc_interface/AbstractController.hh" -#include "mem/ruby/system/MemoryVector.hh" #include "mem/ruby/system/System.hh" +#include "sim/simulate.hh" using namespace std; @@ -86,6 +90,8 @@ RubySystem::RubySystem(const Params *p) // RubyExitCallback* rubyExitCB = new RubyExitCallback(p->stats_filename); registerExitCallback(rubyExitCB); + m_warmup_enabled = false; + m_cooldown_enabled = false; } void @@ -112,6 +118,12 @@ RubySystem::registerAbstractController(AbstractController* cntrl) m_abs_cntrl_vec.push_back(cntrl); } +void +RubySystem::registerSparseMemory(SparseMemory* s) +{ + m_sparse_memory_vector.push_back(s); +} + RubySystem::~RubySystem() { delete m_network_ptr; @@ -157,10 +169,144 @@ RubySystem::printStats(ostream& out) m_network_ptr->printStats(out); } +void +RubySystem::writeCompressedTrace(uint8* raw_data, string filename, + uint64 uncompressed_trace_size) +{ + // Create the checkpoint file for the memory + string thefile = Checkpoint::dir() + "/" + filename.c_str(); + + int fd = creat(thefile.c_str(), 0664); + if (fd < 0) { + perror("creat"); + fatal("Can't open memory trace file '%s'\n", filename); + } + + gzFile compressedMemory = gzdopen(fd, "wb"); + if (compressedMemory == NULL) + fatal("Insufficient memory to allocate compression state for %s\n", + filename); + + if (gzwrite(compressedMemory, raw_data, uncompressed_trace_size) != + uncompressed_trace_size) { + fatal("Write failed on memory trace file '%s'\n", filename); + } + + if (gzclose(compressedMemory)) { + fatal("Close failed on memory trace file '%s'\n", filename); + } + delete raw_data; +} + void RubySystem::serialize(std::ostream &os) { + m_cooldown_enabled = true; + + vector sequencer_map; + Sequencer* sequencer_ptr = NULL; + int cntrl_id = -1; + + + for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { + sequencer_map.push_back(m_abs_cntrl_vec[cntrl]->getSequencer()); + if (sequencer_ptr == NULL) { + sequencer_ptr = sequencer_map[cntrl]; + cntrl_id = cntrl; + } + } + + assert(sequencer_ptr != NULL); + + for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { + if (sequencer_map[cntrl] == NULL) { + sequencer_map[cntrl] = sequencer_ptr; + } + } + + // Create the CacheRecorder and record the cache trace + m_cache_recorder = new CacheRecorder(NULL, 0, sequencer_map); + + for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { + m_abs_cntrl_vec[cntrl]->recordCacheTrace(cntrl, m_cache_recorder); + } + + // save the current tick value + Tick curtick_original = curTick(); + // save the event queue head + Event* eventq_head = eventq->replaceHead(NULL); + + // Schedule an event to start cache cooldown + RubyEvent* e = new RubyEvent(this); + schedule(e,curTick()); + simulate(); + + // Restore eventq head + eventq_head = eventq->replaceHead(eventq_head); + // Restore curTick + curTick(curtick_original); + + uint8* raw_data = NULL; + + if (m_mem_vec_ptr != NULL) { + uint64 memory_trace_size = m_mem_vec_ptr->collatePages(raw_data); + + string memory_trace_file = name() + ".memory.gz"; + writeCompressedTrace(raw_data, memory_trace_file, + memory_trace_size); + + SERIALIZE_SCALAR(memory_trace_file); + SERIALIZE_SCALAR(memory_trace_size); + + } else { + for (int i = 0; i < m_sparse_memory_vector.size(); ++i) { + m_sparse_memory_vector[i]->recordBlocks(cntrl_id, + m_cache_recorder); + } + } + + // Aggergate the trace entries together into a single array + raw_data = new uint8_t[4096]; + uint64 cache_trace_size = m_cache_recorder->aggregateRecords(&raw_data, + 4096); + string cache_trace_file = name() + ".cache.gz"; + writeCompressedTrace(raw_data, cache_trace_file, cache_trace_size); + + SERIALIZE_SCALAR(cache_trace_file); + SERIALIZE_SCALAR(cache_trace_size); + m_cooldown_enabled = false; +} + +void +RubySystem::readCompressedTrace(string filename, uint8*& raw_data, + uint64& uncompressed_trace_size) +{ + // Read the trace file + gzFile compressedTrace; + + // trace file + int fd = open(filename.c_str(), O_RDONLY); + if (fd < 0) { + perror("open"); + fatal("Unable to open trace file %s", filename); + } + + compressedTrace = gzdopen(fd, "rb"); + if (compressedTrace == NULL) { + fatal("Insufficient memory to allocate compression state for %s\n", + filename); + } + + raw_data = new uint8_t[uncompressed_trace_size]; + if (gzread(compressedTrace, raw_data, uncompressed_trace_size) < + uncompressed_trace_size) { + fatal("Unable to read complete trace from file %s\n", filename); + } + + if (gzclose(compressedTrace)) { + fatal("Failed to close cache trace file '%s'\n", filename); + } } void @@ -172,18 +318,95 @@ RubySystem::unserialize(Checkpoint *cp, const string §ion) // value of curTick() // clearStats(); + uint8* uncompressed_trace = NULL; + + if (m_mem_vec_ptr != NULL) { + string memory_trace_file; + uint64 memory_trace_size = 0; + + UNSERIALIZE_SCALAR(memory_trace_file); + UNSERIALIZE_SCALAR(memory_trace_size); + memory_trace_file = cp->cptDir + "/" + memory_trace_file; + + readCompressedTrace(memory_trace_file, uncompressed_trace, + memory_trace_size); + m_mem_vec_ptr->populatePages(uncompressed_trace); + + delete uncompressed_trace; + uncompressed_trace = NULL; + } + + string cache_trace_file; + uint64 cache_trace_size = 0; + + UNSERIALIZE_SCALAR(cache_trace_file); + UNSERIALIZE_SCALAR(cache_trace_size); + cache_trace_file = cp->cptDir + "/" + cache_trace_file; + + readCompressedTrace(cache_trace_file, uncompressed_trace, + cache_trace_size); + m_warmup_enabled = true; + + vector sequencer_map; + Sequencer* t = NULL; + for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { + sequencer_map.push_back(m_abs_cntrl_vec[cntrl]->getSequencer()); + if(t == NULL) t = sequencer_map[cntrl]; + } + + assert(t != NULL); + + for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { + if (sequencer_map[cntrl] == NULL) { + sequencer_map[cntrl] = t; + } + } + + m_cache_recorder = new CacheRecorder(uncompressed_trace, cache_trace_size, + sequencer_map); } void -RubySystem::clearStats() const +RubySystem::startup() { - m_profiler_ptr->clearStats(); - m_network_ptr->clearStats(); + if (m_warmup_enabled) { + // save the current tick value + Tick curtick_original = curTick(); + // save the event queue head + Event* eventq_head = eventq->replaceHead(NULL); + // set curTick to 0 + curTick(0); + + // Schedule an event to start cache warmup + RubyEvent* e = new RubyEvent(this); + schedule(e,curTick()); + simulate(); + + delete m_cache_recorder; + m_cache_recorder = NULL; + m_warmup_enabled = false; + // Restore eventq head + eventq_head = eventq->replaceHead(eventq_head); + // Restore curTick + curTick(curtick_original); + } +} + +void +RubySystem::RubyEvent::process() +{ + if (ruby_system->m_warmup_enabled) { + ruby_system->m_cache_recorder->enqueueNextFetchRequest(); + } else if (ruby_system->m_cooldown_enabled) { + ruby_system->m_cache_recorder->enqueueNextFlushRequest(); + } } void -RubySystem::recordCacheContents(CacheRecorder& tr) const +RubySystem::clearStats() const { + m_profiler_ptr->clearStats(); + m_network_ptr->clearStats(); } #ifdef CHECK_COHERENCE diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index bcc62a518..461abffe2 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,20 +38,34 @@ #include "base/callback.hh" #include "mem/ruby/common/Global.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh" -#include "mem/ruby/system/RubyPort.hh" +#include "mem/ruby/recorder/CacheRecorder.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" +#include "mem/ruby/system/MemoryVector.hh" +#include "mem/ruby/system/SparseMemory.hh" #include "params/RubySystem.hh" #include "sim/sim_object.hh" -class AbstractController; -class CacheRecorder; -class MemoryVector; class Network; class Profiler; class RubySystem : public SimObject { public: + class RubyEvent : public Event + { + public: + RubyEvent(RubySystem* _ruby_system) + { + ruby_system = _ruby_system; + } + private: + void process(); + + RubySystem* ruby_system; + }; + + friend class RubyEvent; + typedef RubySystemParams Params; RubySystem(const Params *p); ~RubySystem(); @@ -92,7 +106,6 @@ class RubySystem : public SimObject return m_mem_vec_ptr; } - void recordCacheContents(CacheRecorder& tr) const; static void printConfig(std::ostream& out); static void printStats(std::ostream& out); void clearStats() const; @@ -106,12 +119,15 @@ class RubySystem : public SimObject void print(std::ostream& out) const; - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + void process(); + void startup(); void registerNetwork(Network*); void registerProfiler(Profiler*); void registerAbstractController(AbstractController*); + void registerSparseMemory(SparseMemory*); private: // Private copy constructor and assignment operator @@ -121,6 +137,11 @@ class RubySystem : public SimObject void init(); static void printSystemConfig(std::ostream& out); + void readCompressedTrace(std::string filename, + uint8*& raw_data, + uint64& uncompressed_trace_size); + void writeCompressedTrace(uint8* raw_data, std::string file, + uint64 uncompressed_trace_size); private: // configuration parameters @@ -131,13 +152,16 @@ class RubySystem : public SimObject static int m_block_size_bits; static uint64 m_memory_size_bytes; static int m_memory_size_bits; - static Network* m_network_ptr; public: static Profiler* m_profiler_ptr; static MemoryVector* m_mem_vec_ptr; std::vector m_abs_cntrl_vec; + bool m_warmup_enabled; + bool m_cooldown_enabled; + CacheRecorder* m_cache_recorder; + std::vector m_sparse_memory_vector; }; inline std::ostream& -- cgit v1.2.3 From bc1c21274e8c3559fe4bd8b8622f1f2afe1efd9b Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 11 Jan 2012 19:24:13 -0500 Subject: Packet: Remove meaningless assert statement --- src/mem/packet.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 57d85af8a..aefaf975d 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -287,8 +287,6 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) } } - assert((bytesValidStart >= 0) && (bytesValidEnd <= getSize())); - // copy partial data into the packet's data array uint8_t *dest = getPtr() + func_offset; uint8_t *src = data + val_offset; -- cgit v1.2.3 From c40ae2c3fbab796a95bd512dd72c29345cbe0dfc Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 11 Jan 2012 19:27:11 -0500 Subject: Packet: Put back part of the assert --- src/mem/packet.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/mem/packet.cc b/src/mem/packet.cc index aefaf975d..64f4fcd14 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -286,6 +286,7 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) "for functional copying!"); } } + assert(bytesValidEnd <= getSize()); // copy partial data into the packet's data array uint8_t *dest = getPtr() + func_offset; -- cgit v1.2.3 From 0e6d6a5e2567abab230395badc57a62efc1c425a Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Thu, 12 Jan 2012 00:35:57 -0600 Subject: PerfectCacheMemory: Remove references to CacheMsg The definition for the class CacheMsg was removed long back. Some declaration had still survived, which was recently removed. Since the PerfectCacheMemory class relied on this particular declaration, its absence let to compilation breaking down. Hence this patch. --- src/mem/ruby/system/PerfectCacheMemory.hh | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'src') diff --git a/src/mem/ruby/system/PerfectCacheMemory.hh b/src/mem/ruby/system/PerfectCacheMemory.hh index 772b3d1f9..b880b6434 100644 --- a/src/mem/ruby/system/PerfectCacheMemory.hh +++ b/src/mem/ruby/system/PerfectCacheMemory.hh @@ -32,7 +32,6 @@ #include "base/hashmap.hh" #include "mem/protocol/AccessPermission.hh" #include "mem/ruby/common/Address.hh" -#include "mem/ruby/common/Global.hh" template struct PerfectCacheLineState @@ -57,10 +56,6 @@ class PerfectCacheMemory static void printConfig(std::ostream& out); - // perform a cache access and see if we hit or not. Return true - // on a hit. - bool tryCacheAccess(const CacheMsg& msg, bool& block_stc, ENTRY*& entry); - // tests to see if an address is present in the cache bool isTagPresent(const Address& address) const; @@ -118,15 +113,6 @@ PerfectCacheMemory::printConfig(std::ostream& out) { } -template -inline bool -PerfectCacheMemory::tryCacheAccess(const CacheMsg& msg, - bool& block_stc, ENTRY*& entry) -{ - panic("not implemented"); - return true; -} - // tests to see if an address is present in the cache template inline bool -- cgit v1.2.3 From 7f782a6c793f30bd7feca66791216263b56f8768 Mon Sep 17 00:00:00 2001 From: Deyuan Guo Date: Thu, 12 Jan 2012 09:58:58 -0500 Subject: mips: definition of MIPS64_QNAN in registers.hh --- src/arch/mips/registers.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/mips/registers.hh b/src/arch/mips/registers.hh index dce7858bf..d3cf1650d 100644 --- a/src/arch/mips/registers.hh +++ b/src/arch/mips/registers.hh @@ -55,7 +55,7 @@ const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; //HI & LO Regs const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;// const uint32_t MIPS32_QNAN = 0x7fbfffff; -const uint64_t MIPS64_QNAN = ULL(0x7fbfffffffffffff); +const uint64_t MIPS64_QNAN = ULL(0x7ff7ffffffffffff); enum FPControlRegNums { FLOATREG_FIR = NumFloatArchRegs, -- cgit v1.2.3 From a40ec5671fa023ad09de902028bd9e9ca1f1d7da Mon Sep 17 00:00:00 2001 From: Deyuan Guo Date: Thu, 12 Jan 2012 09:58:59 -0500 Subject: mips: Fix decoder of two float-convert instructions --- src/arch/mips/isa/decoder.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index 179e409dd..8ebfa66bf 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -1253,7 +1253,7 @@ decode OPCODE_HI default Unknown::unknown() { //When rs=L1 //Note: "1. Format type L is legal only if 64-bit //floating point operations are enabled." - 0x5: decode FUNCTION_HI { + 0x5: decode FUNCTION { format FloatConvertOp { 0x20: cvt_s_l({{ val = Fs_ud; }}, ToSingle); 0x21: cvt_d_l({{ val = Fs_ud; }}, ToDouble); -- cgit v1.2.3 From 31b6941a52f859cf11c3f35ec4c0ac2f2f11eb14 Mon Sep 17 00:00:00 2001 From: Deyuan Guo Date: Thu, 12 Jan 2012 09:59:00 -0500 Subject: mips: Fix bugs in faults.cc/hh and tlb.cc for MIPS_FS --- src/arch/mips/faults.cc | 4 +++- src/arch/mips/faults.hh | 14 +++++++++----- src/arch/mips/tlb.cc | 12 +++++++----- 3 files changed, 19 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc index 9ec93f3fe..00471aece 100644 --- a/src/arch/mips/faults.cc +++ b/src/arch/mips/faults.cc @@ -29,6 +29,8 @@ * Authors: Gabe Black * Korey Sewell * Jaidev Patwardhan + * Zhengxing Li + * Deyuan Guo */ #include "arch/mips/faults.hh" @@ -121,7 +123,7 @@ MipsFaultBase::setExceptionState(ThreadContext *tc, uint8_t excCode) DPRINTF(MipsPRA, "PC: %s\n", pc); bool delay_slot = pc.pc() + sizeof(MachInst) != pc.npc(); tc->setMiscRegNoEffect(MISCREG_EPC, - pc.pc() - delay_slot ? sizeof(MachInst) : 0); + pc.pc() - (delay_slot ? sizeof(MachInst) : 0)); // Set Cause_EXCCODE field CauseReg cause = tc->readMiscReg(MISCREG_CAUSE); diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index 89b6924c6..76d4fff23 100644 --- a/src/arch/mips/faults.hh +++ b/src/arch/mips/faults.hh @@ -29,6 +29,8 @@ * Authors: Gabe Black * Korey Sewell * Jaidev Patwardhan + * Zhengxing Li + * Deyuan Guo */ #ifndef __MIPS_FAULTS_HH__ @@ -87,7 +89,7 @@ class MipsFaultBase : public FaultBase virtual FaultVect base(ThreadContext *tc) const { StatusReg status = tc->readMiscReg(MISCREG_STATUS); - if (status.bev) + if (!status.bev) return tc->readMiscReg(MISCREG_EBASE); else return 0xbfc00200; @@ -166,7 +168,7 @@ class CoprocessorUnusableFault : public MipsFault if (FULL_SYSTEM) { CauseReg cause = tc->readMiscReg(MISCREG_CAUSE); cause.ce = coProcID; - tc->setMiscReg(MISCREG_CAUSE, cause); + tc->setMiscRegNoEffect(MISCREG_CAUSE, cause); } } }; @@ -178,7 +180,8 @@ class InterruptFault : public MipsFault offset(ThreadContext *tc) const { CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE); - return cause.iv ? 0x200 : 0x000; + // offset 0x200 for release 2, 0x180 for release 1. + return cause.iv ? 0x200 : 0x180; } }; @@ -250,9 +253,10 @@ class TlbFault : public AddressFault StaticInstPtr inst = StaticInst::nullStaticInstPtr) { if (FULL_SYSTEM) { - DPRINTF(MipsPRA, "Fault %s encountered.\n", name()); - tc->pcState(this->vect(tc)); + DPRINTF(MipsPRA, "Fault %s encountered.\n", this->name()); + Addr vect = this->vect(tc); setTlbExceptionState(tc, this->code()); + tc->pcState(vect); } else { AddressFault::invoke(tc, inst); } diff --git a/src/arch/mips/tlb.cc b/src/arch/mips/tlb.cc index 57d8849e1..b3ed09621 100644 --- a/src/arch/mips/tlb.cc +++ b/src/arch/mips/tlb.cc @@ -29,6 +29,8 @@ * Authors: Nathan Binkert * Steve Reinhardt * Jaidev Patwardhan + * Zhengxing Li + * Deyuan Guo */ #include @@ -350,7 +352,7 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc) } if (Valid == false) { - return new InvalidFault(Asid, vaddr, vpn, false); + return new TlbInvalidFault(Asid, vaddr, VPN, false); } else { // Ok, this is really a match, set paddr Addr PAddr; @@ -366,7 +368,7 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc) } } else { // Didn't find any match, return a TLB Refill Exception - return new RefillFault(Asid, vaddr, vpn, false); + return new TlbRefillFault(Asid, vaddr, VPN, false); } } return checkCacheability(req); @@ -445,10 +447,10 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write) } if (Valid == false) { - return new InvalidFault(Asid, vaddr, VPN, true); + return new TlbInvalidFault(Asid, vaddr, VPN, write); } else { // Ok, this is really a match, set paddr - if (!Dirty) { + if (!Dirty && write) { return new TlbModifiedFault(Asid, vaddr, VPN); } Addr PAddr; @@ -464,7 +466,7 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write) } } else { // Didn't find any match, return a TLB Refill Exception - return new RefillFault(Asid, vaddr, VPN, true); + return new TlbRefillFault(Asid, vaddr, VPN, write); } } return checkCacheability(req); -- cgit v1.2.3 From 4a59cf00b4b03b63e30a89f1b7f27dbd8bca4f3a Mon Sep 17 00:00:00 2001 From: Deyuan Guo Date: Thu, 12 Jan 2012 09:59:01 -0500 Subject: mips: compatibility between MIPS_SE and cross compiler from CodeSorcery --- src/arch/mips/linux/process.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 156d4ea05..0982e05cb 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -55,7 +55,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->sysname, "Linux"); strcpy(name->nodename,"m5.eecs.umich.edu"); - strcpy(name->release, "2.4.20"); + strcpy(name->release, "2.6.35"); strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "mips"); -- cgit v1.2.3 From a7394ad6807bd5e85f680184bf308673ca00534a Mon Sep 17 00:00:00 2001 From: Maximilien Breughe Date: Thu, 12 Jan 2012 10:15:00 -0500 Subject: inorder: MDU deadlock fix --- src/cpu/inorder/resources/mult_div_unit.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc index 0ff05252c..ab0081787 100644 --- a/src/cpu/inorder/resources/mult_div_unit.cc +++ b/src/cpu/inorder/resources/mult_div_unit.cc @@ -299,6 +299,7 @@ MultDivUnit::exeMulDiv(int slot_num) } mult_div_req->setProcessing(false); + cpu->wakeCPU(); } void -- cgit v1.2.3