From 5f4297e865eab5b28c2c17711ecf590934961335 Mon Sep 17 00:00:00 2001 From: Erik Hallnor Date: Tue, 8 Jun 2004 17:31:04 -0400 Subject: [PATCH 01/19] Add the capability to read and write memory trace files. Currently is cycle accurate for a single thread FullCPU. --HG-- extra : convert_revision : f8fe545313eb307cc6f5ff2c23894cc9870b1d5b --- cpu/trace/reader/m5_reader.cc | 93 +++++++++++++ cpu/trace/reader/m5_reader.hh | 67 ++++++++++ cpu/trace/reader/mem_trace_reader.cc | 37 ++++++ cpu/trace/reader/mem_trace_reader.hh | 57 ++++++++ cpu/trace/trace_cpu.cc | 192 +++++++++++++++++++++++++++ cpu/trace/trace_cpu.hh | 151 +++++++++++++++++++++ 6 files changed, 597 insertions(+) create mode 100644 cpu/trace/reader/m5_reader.cc create mode 100644 cpu/trace/reader/m5_reader.hh create mode 100644 cpu/trace/reader/mem_trace_reader.cc create mode 100644 cpu/trace/reader/mem_trace_reader.hh create mode 100644 cpu/trace/trace_cpu.cc create mode 100644 cpu/trace/trace_cpu.hh diff --git a/cpu/trace/reader/m5_reader.cc b/cpu/trace/reader/m5_reader.cc new file mode 100644 index 0000000000..d6ec7be505 --- /dev/null +++ b/cpu/trace/reader/m5_reader.cc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of a memory trace reader for a M5 memory trace. + */ + +#include "cpu/trace/reader/m5_reader.hh" +#include "mem/trace/m5_format.hh" +#include "mem/mem_cmd.hh" +#include "sim/builder.hh" + +using namespace std; + +M5Reader::M5Reader(const string &name, const string &filename) + : MemTraceReader(name) +{ + traceFile.open(filename.c_str(), ios::binary); +} + +Tick +M5Reader::getNextReq(MemReqPtr &req) +{ + M5Format ref; + + MemReqPtr tmp_req; + // Need to read EOF char before eof() will return true. + traceFile.read((char*) &ref, sizeof(ref)); + if (!traceFile.eof()) { + //traceFile.read((char*) &ref, sizeof(ref)); + int gcount = traceFile.gcount(); + assert(gcount != 0 || traceFile.eof()); + assert(gcount == sizeof(ref)); + assert(ref.cmd < 12); + tmp_req = new MemReq(); + tmp_req->paddr = ref.paddr; + tmp_req->asid = ref.asid; + tmp_req->cmd = (MemCmdEnum)ref.cmd; + tmp_req->size = ref.size; + tmp_req->dest = ref.dest; + } else { + ref.cycle = 0; + } + req = tmp_req; + return ref.cycle; +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(M5Reader) + + Param filename; + +END_DECLARE_SIM_OBJECT_PARAMS(M5Reader) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(M5Reader) + + INIT_PARAM(filename, "trace file") + +END_INIT_SIM_OBJECT_PARAMS(M5Reader) + + +CREATE_SIM_OBJECT(M5Reader) +{ + return new M5Reader(getInstanceName(), filename); +} + +REGISTER_SIM_OBJECT("M5Reader", M5Reader) diff --git a/cpu/trace/reader/m5_reader.hh b/cpu/trace/reader/m5_reader.hh new file mode 100644 index 0000000000..d787874611 --- /dev/null +++ b/cpu/trace/reader/m5_reader.hh @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Definition of a memory trace reader for a M5 memory trace. + */ + +#ifndef __M5_READER_HH__ +#define __M5_READER_HH__ + +#include + +#include "cpu/trace/reader/mem_trace_reader.hh" + +/** + * A memory trace reader for an M5 memory trace. @sa M5Writer. + */ +class M5Reader : public MemTraceReader +{ + /** The traceFile. */ + std::ifstream traceFile; + + std::string fn; + + public: + /** + * Construct an M5 memory trace reader. + */ + M5Reader(const std::string &name, const std::string &filename); + + + /** + * Read the next request from the trace. Returns the request in the + * provided MemReqPtr and the cycle of the request in the return value. + * @param req Return the next request from the trace. + * @return The cycle the reference was started. + */ + virtual Tick getNextReq(MemReqPtr &req); +}; + +#endif // __M5_READER_HH__ diff --git a/cpu/trace/reader/mem_trace_reader.cc b/cpu/trace/reader/mem_trace_reader.cc new file mode 100644 index 0000000000..c6fc53f511 --- /dev/null +++ b/cpu/trace/reader/mem_trace_reader.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * SimObject Declaration of pure virtual MemTraceReader class. + */ + +#include "cpu/trace/reader/mem_trace_reader.hh" +#include "sim/param.hh" + +DEFINE_SIM_OBJECT_CLASS_NAME("MemTraceReader", MemTraceReader); diff --git a/cpu/trace/reader/mem_trace_reader.hh b/cpu/trace/reader/mem_trace_reader.hh new file mode 100644 index 0000000000..5da99a498b --- /dev/null +++ b/cpu/trace/reader/mem_trace_reader.hh @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Definitions for a pure virtual interface to a memory trace reader. + */ + +#ifndef __MEM_TRACE_READER_HH__ +#define __MEM_TRACE_READER_HH__ + +#include "sim/sim_object.hh" +#include "mem/mem_req.hh" // For MemReqPtr + +/** + * Pure virtual base class for memory trace readers. + */ +class MemTraceReader : public SimObject +{ + public: + /** Construct this MemoryTrace reader. */ + MemTraceReader(const std::string &name) : SimObject(name) {} + + /** + * Read the next request from the trace. Returns the request in the + * provided MemReqPtr and the cycle of the request in the return value. + * @param req Return the next request from the trace. + * @return The cycle of the request, 0 if none in trace. + */ + virtual Tick getNextReq(MemReqPtr &req) = 0; +}; + +#endif //__MEM_TRACE_READER_HH__ diff --git a/cpu/trace/trace_cpu.cc b/cpu/trace/trace_cpu.cc new file mode 100644 index 0000000000..6fdc320347 --- /dev/null +++ b/cpu/trace/trace_cpu.cc @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of a memory trace CPU object. Uses a memory trace to drive the + * provided memory hierarchy. + */ + +#include // For min + +#include "cpu/trace/trace_cpu.hh" +#include "cpu/trace/reader/mem_trace_reader.hh" +#include "mem/base_mem.hh" // For PARAM constructor +#include "mem/mem_interface.hh" +#include "sim/builder.hh" +#include "sim/sim_events.hh" + +using namespace std; + +TraceCPU::TraceCPU(const string &name, + MemInterface *icache_interface, + MemInterface *dcache_interface, + MemTraceReader *inst_trace, + MemTraceReader *data_trace, + int icache_ports, + int dcache_ports) + : BaseCPU(name, 1), icacheInterface(icache_interface), + dcacheInterface(dcache_interface), instTrace(inst_trace), + dataTrace(data_trace), icachePorts(icache_ports), + dcachePorts(dcache_ports), outstandingRequests(0), tickEvent(this) +{ + if (instTrace) { + assert(icacheInterface); + nextInstCycle = instTrace->getNextReq(nextInstReq); + } + if (dataTrace) { + assert(dcacheInterface); + nextDataCycle = dataTrace->getNextReq(nextDataReq); + } + tickEvent.schedule(0); +} + +void +TraceCPU::tick() +{ + assert(outstandingRequests >= 0); + assert(outstandingRequests < 1000); + int instReqs = 0; + int dataReqs = 0; + + // Do data first to match tracing with FullCPU dumps + + while (nextDataReq && (dataReqs < dcachePorts) && + curTick >= nextDataCycle) { + if (dcacheInterface->isBlocked()) + break; + + ++outstandingRequests; + ++dataReqs; + nextDataReq->time = curTick; + nextDataReq->completionEvent = + new TraceCompleteEvent(nextDataReq, this); + dcacheInterface->access(nextDataReq); + nextDataCycle = dataTrace->getNextReq(nextDataReq); + } + + while (nextInstReq && (instReqs < icachePorts) && + curTick >= nextInstCycle) { + if (icacheInterface->isBlocked()) + break; + + nextInstReq->time = curTick; + if (nextInstReq->cmd == Squash) { + icacheInterface->squash(nextInstReq->asid); + } else { + ++outstandingRequests; + ++instReqs; + nextInstReq->completionEvent = + new TraceCompleteEvent(nextInstReq, this); + icacheInterface->access(nextInstReq); + } + nextInstCycle = instTrace->getNextReq(nextInstReq); + } + + if (!nextInstReq && !nextDataReq) { + // No more requests to send. Finish trailing events and exit. + if (mainEventQueue.empty()) { + new SimExitEvent("Finshed Memory Trace"); + } else { + tickEvent.schedule(mainEventQueue.nextEventTime() + 1); + } + } else { + tickEvent.schedule(max(curTick + 1, + min(nextInstCycle, nextDataCycle))); + } +} + +void +TraceCPU::completeRequest(MemReqPtr& req) +{ + --outstandingRequests; +} + +void +TraceCompleteEvent::process() +{ + tester->completeRequest(req); +} + +const char * +TraceCompleteEvent::description() +{ + return "trace access complete"; +} + +TraceCPU::TickEvent::TickEvent(TraceCPU *c) + : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) +{ +} + +void +TraceCPU::TickEvent::process() +{ + cpu->tick(); +} + +const char * +TraceCPU::TickEvent::description() +{ + return "TraceCPU tick event"; +} + + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(TraceCPU) + + SimObjectParam icache; + SimObjectParam dcache; + SimObjectParam inst_trace; + SimObjectParam data_trace; + Param inst_ports; + Param data_ports; + +END_DECLARE_SIM_OBJECT_PARAMS(TraceCPU) + +BEGIN_INIT_SIM_OBJECT_PARAMS(TraceCPU) + + INIT_PARAM_DFLT(icache, "instruction cache", NULL), + INIT_PARAM_DFLT(dcache, "data cache", NULL), + INIT_PARAM_DFLT(inst_trace, "instruction trace", NULL), + INIT_PARAM_DFLT(data_trace, "data trace", NULL), + INIT_PARAM_DFLT(inst_ports, "instruction cache read ports", 4), + INIT_PARAM_DFLT(data_ports, "data cache read/write ports", 4) + +END_INIT_SIM_OBJECT_PARAMS(TraceCPU) + +CREATE_SIM_OBJECT(TraceCPU) +{ + return new TraceCPU(getInstanceName(), + (icache) ? icache->getInterface() : NULL, + (dcache) ? dcache->getInterface() : NULL, + inst_trace, data_trace, inst_ports, data_ports); +} + +REGISTER_SIM_OBJECT("TraceCPU", TraceCPU) + diff --git a/cpu/trace/trace_cpu.hh b/cpu/trace/trace_cpu.hh new file mode 100644 index 0000000000..13a204f4e5 --- /dev/null +++ b/cpu/trace/trace_cpu.hh @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of a memory trace CPU object. Uses a memory trace to drive the + * provided memory hierarchy. + */ + +#ifndef __TRACE_CPU_HH__ +#define __TRACE_CPU_HH__ + +#include + +#include "cpu/base_cpu.hh" +#include "mem/mem_req.hh" // for MemReqPtr +#include "sim/eventq.hh" // for Event + +// Forward declaration. +class MemInterface; +class MemTraceReader; + +/** + * A cpu object for running memory traces through a memory hierarchy. + */ +class TraceCPU : public BaseCPU +{ + /** Interface for instruction trace requests, if any. */ + MemInterface *icacheInterface; + /** Interface for data trace requests, if any. */ + MemInterface *dcacheInterface; + + /** Instruction reference trace. */ + MemTraceReader *instTrace; + /** Data reference trace. */ + MemTraceReader *dataTrace; + + /** Number of Icache read ports. */ + int icachePorts; + /** Number of Dcache read/write ports. */ + int dcachePorts; + + /** Number of outstanding requests. */ + int outstandingRequests; + + /** Cycle of the next instruction request, 0 if not available. */ + Tick nextInstCycle; + /** Cycle of the next data request, 0 if not available. */ + Tick nextDataCycle; + + /** Next instruction request. */ + MemReqPtr nextInstReq; + /** Next data request. */ + MemReqPtr nextDataReq; + + /** + * Event to call the TraceCPU::tick + */ + class TickEvent : public Event + { + private: + /** The associated CPU */ + TraceCPU *cpu; + + public: + /** + * Construct this event; + */ + TickEvent(TraceCPU *c); + + /** + * Call the tick function. + */ + void process(); + + /** + * Return a string description of this event. + */ + const char *description(); + }; + + TickEvent tickEvent; + + public: + /** + * Construct a TraceCPU object. + */ + TraceCPU(const std::string &name, + MemInterface *icache_interface, + MemInterface *dcache_interface, + MemTraceReader *inst_trace, + MemTraceReader *data_trace, + int icache_ports, + int dcache_ports); + + /** + * Perform all the accesses for one cycle. + */ + void tick(); + + /** + * Handle a completed memory request. + */ + void completeRequest(MemReqPtr &req); +}; + +class TraceCompleteEvent : public Event +{ + MemReqPtr req; + TraceCPU *tester; + + public: + + TraceCompleteEvent(MemReqPtr &_req, TraceCPU *_tester) + : Event(&mainEventQueue), req(_req), tester(_tester) + { + setFlags(AutoDelete); + } + + void process(); + + virtual const char *description(); +}; + +#endif //__TRACE_CPU_HH__ + From e7c7c92184e7a077ee0a5a80b62e0d7797d73ddb Mon Sep 17 00:00:00 2001 From: Erik Hallnor Date: Tue, 8 Jun 2004 19:52:49 -0400 Subject: [PATCH 02/19] Tracing now works for upto 4 threads. Easy change to get it to work for more, but I don't have any test handy to test it. cpu/trace/reader/m5_reader.cc: Add thread num. cpu/trace/trace_cpu.cc: Increase thread count to 4, might want to make this a parameter (but it only really costs us storage). --HG-- extra : convert_revision : 97cd7843668a3ef85aad06e3180dc04d2ca30ac1 --- cpu/trace/reader/m5_reader.cc | 2 ++ cpu/trace/trace_cpu.cc | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cpu/trace/reader/m5_reader.cc b/cpu/trace/reader/m5_reader.cc index d6ec7be505..a1ada38a2b 100644 --- a/cpu/trace/reader/m5_reader.cc +++ b/cpu/trace/reader/m5_reader.cc @@ -61,6 +61,8 @@ M5Reader::getNextReq(MemReqPtr &req) tmp_req = new MemReq(); tmp_req->paddr = ref.paddr; tmp_req->asid = ref.asid; + // Assume asid == thread_num + tmp_req->thread_num = ref.asid; tmp_req->cmd = (MemCmdEnum)ref.cmd; tmp_req->size = ref.size; tmp_req->dest = ref.dest; diff --git a/cpu/trace/trace_cpu.cc b/cpu/trace/trace_cpu.cc index 6fdc320347..6122fc7866 100644 --- a/cpu/trace/trace_cpu.cc +++ b/cpu/trace/trace_cpu.cc @@ -50,7 +50,7 @@ TraceCPU::TraceCPU(const string &name, MemTraceReader *data_trace, int icache_ports, int dcache_ports) - : BaseCPU(name, 1), icacheInterface(icache_interface), + : BaseCPU(name, 4), icacheInterface(icache_interface), dcacheInterface(dcache_interface), instTrace(inst_trace), dataTrace(data_trace), icachePorts(icache_ports), dcachePorts(dcache_ports), outstandingRequests(0), tickEvent(this) @@ -78,10 +78,10 @@ TraceCPU::tick() while (nextDataReq && (dataReqs < dcachePorts) && curTick >= nextDataCycle) { + assert(nextDataReq->thread_num < 4 && "Not enough threads"); if (dcacheInterface->isBlocked()) break; - ++outstandingRequests; ++dataReqs; nextDataReq->time = curTick; nextDataReq->completionEvent = @@ -92,6 +92,7 @@ TraceCPU::tick() while (nextInstReq && (instReqs < icachePorts) && curTick >= nextInstCycle) { + assert(nextInstReq->thread_num < 4 && "Not enough threads"); if (icacheInterface->isBlocked()) break; @@ -99,7 +100,6 @@ TraceCPU::tick() if (nextInstReq->cmd == Squash) { icacheInterface->squash(nextInstReq->asid); } else { - ++outstandingRequests; ++instReqs; nextInstReq->completionEvent = new TraceCompleteEvent(nextInstReq, this); @@ -124,7 +124,6 @@ TraceCPU::tick() void TraceCPU::completeRequest(MemReqPtr& req) { - --outstandingRequests; } void From 12d1b12043b916426f07db093448979cdcc537bb Mon Sep 17 00:00:00 2001 From: Erik Hallnor Date: Tue, 8 Jun 2004 20:11:40 -0400 Subject: [PATCH 03/19] Make TraceCPU only compile in non-fullsystem. --HG-- extra : convert_revision : 5df611ae03f41093257672c0ad46bfddc58e515c From 7edeb34905c5ed0207f1ab1af6b5c4a8ea3a86b3 Mon Sep 17 00:00:00 2001 From: Erik Hallnor Date: Wed, 9 Jun 2004 14:41:06 -0400 Subject: [PATCH 04/19] Don't print 0 stats for memory commands we don't see. --HG-- extra : convert_revision : e72c8bec85c72a48b0b5997d184922faf46c456c From 1c782ad134c0f67263bfbc025472839481b59e57 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 9 Jun 2004 20:46:29 -0700 Subject: [PATCH 05/19] Minor restructuring of Python config code, mostly to avoid walking the source tree for *.odesc files every time we run the script. This is now factored out into load_odesc.py, which should be used to generate m5odescs.py, which is then used as the source of object & parameter definitions. util/config/m5configbase.py: - Move odesc loading code to separate load_odescs.py, so maybe someday that can be done once at build time. - Print out children of a node in the order they are added. - Automatically assign a parent-less node to the first node for which it is used as the value of a parameter. (Easier demonstrated than explained.) - Calculate object paths dynamically when requested rather than trying to keep them up to date as objects get assigned to parents. --HG-- rename : util/config/m5config.py => util/config/m5configbase.py extra : convert_revision : 2183a09d32f3862ab377e0a929715f30505a03cb --- util/config/{m5config.py => m5configbase.py} | 253 ++++++------------- 1 file changed, 73 insertions(+), 180 deletions(-) rename util/config/{m5config.py => m5configbase.py} (79%) diff --git a/util/config/m5config.py b/util/config/m5configbase.py similarity index 79% rename from util/config/m5config.py rename to util/config/m5configbase.py index 9aa3e0387f..2daf5d94d8 100644 --- a/util/config/m5config.py +++ b/util/config/m5configbase.py @@ -157,6 +157,21 @@ class MetaConfigNode(type): print "Error setting '%s' default on class '%s'\n" \ % (pname, cls.__name__), exc + # Set the class's parameter dictionary given a code string of + # parameter initializers (as from an object description file). + # Note that the caller must pass in the namespace in which to + # execute the code (usually the caller's globals()), since if we + # call globals() from inside this function all we get is this + # module's internal scope. + def init_params(cls, init_code, ctx): + dict = {} + try: + exec fixPythonIndentation(init_code) in ctx, dict + except Exception, exc: + print "Error in %s.init_params:" % cls.__name__, exc + raise + cls.set_param_dict(dict) + # Lookup a parameter description by name in the given class. Use # the _param_bases list defined in __init__ to go up the # inheritance hierarchy if necessary. @@ -220,14 +235,13 @@ class ConfigNode(object): % (self.__class__.__name__, _name, type(_name)) self._name = _name self._parent = _parent - self._children = {} if (_parent): - _parent.__addChild(self) - # Set up absolute path from root. - if (_parent and _parent._path != 'Universe'): - self._path = _parent._path + '.' + self._name - else: - self._path = self._name + _parent._add_child(self) + self._children = {} + # keep a list of children in addition to the dictionary keys + # so we can remember the order they were added and print them + # out in that order. + self._child_list = [] # When printing (e.g. to .ini file), just give the name. def __str__(self): @@ -248,7 +262,7 @@ class ConfigNode(object): # Set attribute. All attribute assignments go through here. Must # be private attribute (starts with '_') or valid parameter entry. # Basically identical to MetaConfigClass.__setattr__(), except - # this handles instances rather than class attributes. + # this sets attributes on specific instances rather than on classes. def __setattr__(self, attr_name, value): if attr_name.startswith('_'): object.__setattr__(self, attr_name, value) @@ -261,11 +275,30 @@ class ConfigNode(object): % (self.__class__.__name__, attr_name) # It's ok: set attribute by delegating to 'object' class. # Note the use of param.make_value() to verify/canonicalize - # the assigned value - object.__setattr__(self, attr_name, param.make_value(value)) + # the assigned value. + v = param.make_value(value) + object.__setattr__(self, attr_name, v) + + # A little convenient magic: if the parameter is a ConfigNode + # (or vector of ConfigNodes, or anything else with a + # '_set_parent_if_none' function attribute) that does not have + # a parent (and so is not part of the configuration + # hierarchy), then make this node its parent. + if hasattr(v, '_set_parent_if_none'): + v._set_parent_if_none(self) + + def _path(self): + # Return absolute path from root. + if not self._parent and self._name != 'Universe': + print >> sys.stderr, "Warning:", self._name, "has no parent" + parent_path = self._parent and self._parent._path() + if parent_path and parent_path != 'Universe': + return parent_path + '.' + self._name + else: + return self._name # Add a child to this node. - def __addChild(self, new_child): + def _add_child(self, new_child): # set child's parent before calling this function assert new_child._parent == self if not isinstance(new_child, ConfigNode): @@ -276,6 +309,7 @@ class ConfigNode(object): "Node '%s' already has a child '%s'" \ % (self._name, new_child._name) self._children[new_child._name] = new_child + self._child_list += [new_child] # operator overload for '+='. You can say "node += child" to add # a child that was created with parent=None. An early attempt @@ -285,27 +319,28 @@ class ConfigNode(object): raise AttributeError, \ "Node '%s' already has a parent" % new_child._name new_child._parent = self - self.__addChild(new_child) + self._add_child(new_child) return self + # Set this instance's parent to 'parent' if it doesn't already + # have one. See ConfigNode.__setattr__(). + def _set_parent_if_none(self, parent): + if self._parent == None: + parent += self + # Print instance info to .ini file. def _instantiate(self): - print '[' + self._path + ']' # .ini section header - if self._children: - # instantiate children in sorted order for backward - # compatibility (else we can end up with cpu1 before cpu0). - child_names = self._children.keys() - child_names.sort() - print 'children =', - for child_name in child_names: - print child_name, - print + print '[' + self._path() + ']' # .ini section header + if self._child_list: + # instantiate children in same order they were added for + # backward compatibility (else we can end up with cpu1 + # before cpu0). + print 'children =', ' '.join([c._name for c in self._child_list]) self._instantiateParams() print # recursively dump out children - if self._children: - for child_name in child_names: - self._children[child_name]._instantiate() + for c in self._child_list: + c._instantiate() # ConfigNodes have no parameters. Overridden by SimObject. def _instantiateParams(self): @@ -373,9 +408,6 @@ class SimObject(ConfigNode): def isNullPointer(value): return isinstance(value, NullSimObject) -def isSimObjectType(ptype): - return issubclass(ptype, SimObject) - # Regular parameter. class Param(object): # Constructor. E.g., Param(Int, "number of widgets", 5) @@ -391,7 +423,7 @@ class Param(object): # nothing to do if None or already correct type. Also allow NULL # pointer to be assigned where a SimObject is expected. if value == None or isinstance(value, self.ptype) or \ - isNullPointer(value) and isSimObjectType(self.ptype): + isNullPointer(value) and issubclass(self.ptype, ConfigNode): return value # this type conversion will raise an exception if it's illegal return self.ptype(value) @@ -414,12 +446,21 @@ class Param(object): # storing these instead of a raw Python list is that we can override # the __str__() method to not print out '[' and ']' in the .ini file. class _VectorParamValue(object): - def __init__(self, list): - self.value = list + def __init__(self, value): + assert isinstance(value, list) or value == None + self.value = value def __str__(self): return ' '.join(map(str, self.value)) + # Set member instance's parents to 'parent' if they don't already + # have one. Extends "magic" parenting of ConfigNodes to vectors + # of ConfigNodes as well. See ConfigNode.__setattr__(). + def _set_parent_if_none(self, parent): + if self.value and hasattr(self.value[0], '_set_parent_if_none'): + for v in self.value: + v._set_parent_if_none(parent) + # Vector-valued parameter description. Just like Param, except that # the value is a vector (list) of the specified type instead of a # single value. @@ -623,7 +664,7 @@ false = False true = True # Some memory range specifications use this as a default upper bound. -MAX_ADDR = 2 ** 63 +MAX_ADDR = 2**64 - 1 # For power-of-two sizing, e.g. 64*K gives an integer value 65536. K = 1024 @@ -631,109 +672,6 @@ M = K*K G = K*M ##################################################################### -# -# Object description loading. -# -# The final step is to define the classes corresponding to M5 objects -# and their parameters. These classes are described in .odesc files -# in the source tree. This code walks the tree to find those files -# and loads up the descriptions (by evaluating them in pieces as -# Python code). -# -# -# Because SimObject classes inherit from other SimObject classes, and -# can use arbitrary other SimObject classes as parameter types, we -# have to do this in three steps: -# -# 1. Walk the tree to find all the .odesc files. Note that the base -# of the filename *must* match the class name. This step builds a -# mapping from class names to file paths. -# -# 2. Start generating empty class definitions (via def_class()) using -# the OBJECT field of the .odesc files to determine inheritance. -# def_class() recurses on demand to define needed base classes before -# derived classes. -# -# 3. Now that all of the classes are defined, go through the .odesc -# files one more time loading the parameter descriptions. -# -##################################################################### - -# dictionary: maps object names to file paths -odesc_file = {} - -# dictionary: maps object names to boolean flag indicating whether -# class definition was loaded yet. Since SimObject is defined in -# m5.config.py, count it as loaded. -odesc_loaded = { 'SimObject': True } - -# Find odesc files in namelist and initialize odesc_file and -# odesc_loaded dictionaries. Called via os.path.walk() (see below). -def find_odescs(process, dirpath, namelist): - # Prune out SCCS directories so we don't process s.*.odesc files. - i = 0 - while i < len(namelist): - if namelist[i] == "SCCS": - del namelist[i] - else: - i = i + 1 - # Find .odesc files and record them. - for name in namelist: - if name.endswith('.odesc'): - objname = name[:name.rindex('.odesc')] - path = os.path.join(dirpath, name) - if odesc_file.has_key(objname): - print "Warning: duplicate object names:", \ - odesc_file[objname], path - odesc_file[objname] = path - odesc_loaded[objname] = False - - -# Regular expression string for parsing .odesc files. -file_re_string = r''' -^OBJECT: \s* (\w+) \s* \( \s* (\w+) \s* \) -\s* -^PARAMS: \s*\n ( (\s+.*\n)* ) -''' - -# Compiled regular expression object. -file_re = re.compile(file_re_string, re.MULTILINE | re.VERBOSE) - -# .odesc file parsing function. Takes a filename and returns tuple of -# object name, object base, and parameter description section. -def parse_file(path): - f = open(path, 'r').read() - m = file_re.search(f) - if not m: - print "Can't parse", path - sys.exit(1) - return (m.group(1), m.group(2), m.group(3)) - -# Define SimObject class based on description in specified filename. -# Class itself is empty except for _name attribute; parameter -# descriptions will be loaded later. Will recurse to define base -# classes as needed before defining specified class. -def def_class(path): - # load & parse file - (obj, parent, params) = parse_file(path) - # check to see if base class is defined yet; define it if not - if not odesc_loaded.has_key(parent): - print "No .odesc file found for", parent - sys.exit(1) - if not odesc_loaded[parent]: - def_class(odesc_file[parent]) - # define the class. The _name attribute of the class lets us - # track the actual SimObject class name even when we derive new - # subclasses in scripts (to provide new parameter value settings). - s = "class %s(%s): _name = '%s'" % (obj, parent, obj) - try: - # execute in global namespace, so new class will be globally - # visible - exec s in globals() - except Exception, exc: - print "Object error in %s:" % path, exc - # mark this file as loaded - odesc_loaded[obj] = True # Munge an arbitrary Python code string to get it to execute (mostly # dealing with indentation). Stolen from isa_parser.py... see @@ -745,51 +683,6 @@ def fixPythonIndentation(s): s = 'if 1:\n' + s return s -# Load parameter descriptions from .odesc file. Object class must -# already be defined. -def def_params(path): - # load & parse file - (obj_name, parent_name, param_code) = parse_file(path) - # initialize param dict - param_dict = {} - # execute parameter descriptions. - try: - # "in globals(), param_dict" makes exec use the current - # globals as the global namespace (so all of the Param - # etc. objects are visible) and param_dict as the local - # namespace (so the newly defined parameter variables will be - # entered into param_dict). - exec fixPythonIndentation(param_code) in globals(), param_dict - except Exception, exc: - print "Param error in %s:" % path, exc - return - # Convert object name string to Python class object - obj = eval(obj_name) - # Set the object's parameter description dictionary (see MetaConfigNode). - obj.set_param_dict(param_dict) - - -# Walk directory tree to find .odesc files. -# Someday we'll have to make the root path an argument instead of -# hard-coding it. For now the assumption is you're running this in -# util/config. -root = '../..' -os.path.walk(root, find_odescs, None) - -# Iterate through file dictionary and define classes. -for objname, path in odesc_file.iteritems(): - if not odesc_loaded[objname]: - def_class(path) - -sim_object_list = odesc_loaded.keys() -sim_object_list.sort() - -# Iterate through files again and load parameters. -for path in odesc_file.itervalues(): - def_params(path) - -##################################################################### - # Hook to generate C++ parameter code. def gen_sim_code(file): for objname in sim_object_list: From 7b24ae00dc2b3f503a15c28a7728cfc9a3e9299f Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 9 Jun 2004 21:01:20 -0700 Subject: [PATCH 06/19] Rename '*.odesc' files to '*.od'. --HG-- extra : convert_revision : 68b4f1cc414ab67e7bd19682854ef3f0b28986c0 From 22fe77f2283c130a1746c68d1ed63f2a242390a5 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Thu, 10 Jun 2004 01:02:33 -0400 Subject: [PATCH 07/19] lif kernelt stats out of tru64 directory cpu/exec_context.hh: change this to reflect the lifted kernel stats file. --HG-- extra : convert_revision : 0dda3babdf51ee7a57430af69c7e20322b4eb622 --- cpu/exec_context.hh | 2 +- kern/kernel_stats.cc | 391 +++++++++++++++++++++++++++++++++++++++++++ kern/kernel_stats.hh | 63 +++++++ 3 files changed, 455 insertions(+), 1 deletion(-) create mode 100644 kern/kernel_stats.cc create mode 100644 kern/kernel_stats.hh diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index a62225f1b5..7409095e27 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -44,7 +44,7 @@ class BaseCPU; #include "targetarch/alpha_memory.hh" class MemoryController; -#include "kern/tru64/kernel_stats.hh" +#include "kern/kernel_stats.hh" #include "sim/system.hh" #include "sim/sw_context.hh" diff --git a/kern/kernel_stats.cc b/kern/kernel_stats.cc new file mode 100644 index 0000000000..de944329a3 --- /dev/null +++ b/kern/kernel_stats.cc @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "base/statistics.hh" +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "kern/kernel_stats.hh" +#include "sim/stats.hh" +#include "sim/sw_context.hh" +#include "targetarch/isa_traits.hh" +#include "targetarch/osfpal.hh" +#include "targetarch/syscalls.hh" + +using namespace std; +using namespace Stats; + +class KSData +{ + private: + string _name; + ExecContext *xc; + BaseCPU *cpu; + + public: + KSData(ExecContext *_xc, BaseCPU *_cpu) + : xc(_xc), cpu(_cpu), iplLast(0), iplLastTick(0), lastUser(false), + lastModeTick(0) + {} + + const string &name() { return _name; } + void regStats(const string &name); + + public: + Scalar<> _arm; + Scalar<> _quiesce; + Scalar<> _ivlb; + Scalar<> _ivle; + Scalar<> _hwrei; + + Vector<> _iplCount; + Vector<> _iplGood; + Vector<> _iplTicks; + Formula _iplUsed; + + Vector<> _callpal; + Vector<> _syscall; + Vector<> _faults; + + Vector<> _mode; + Vector<> _modeGood; + Formula _modeFraction; + Vector<> _modeTicks; + + Scalar<> _swap_context; + + private: + int iplLast; + Tick iplLastTick; + + bool lastUser; + Tick lastModeTick; + + public: + void swpipl(int ipl); + void mode(bool user); + void callpal(int code); +}; + +KernelStats::KernelStats(ExecContext *xc, BaseCPU *cpu) +{ data = new KSData(xc, cpu); } + +KernelStats::~KernelStats() +{ delete data; } + +void +KernelStats::regStats(const string &name) +{ data->regStats(name); } + +void +KSData::regStats(const string &name) +{ + _name = name; + + _arm + .name(name + ".inst.arm") + .desc("number of arm instructions executed") + ; + + _quiesce + .name(name + ".inst.quiesce") + .desc("number of quiesce instructions executed") + ; + + _ivlb + .name(name + ".inst.ivlb") + .desc("number of ivlb instructions executed") + ; + + _ivle + .name(name + ".inst.ivle") + .desc("number of ivle instructions executed") + ; + + _hwrei + .name(name + ".inst.hwrei") + .desc("number of hwrei instructions executed") + ; + + _iplCount + .init(32) + .name(name + ".ipl_count") + .desc("number of times we switched to this ipl") + .flags(total | pdf | nozero | nonan) + ; + + _iplGood + .init(32) + .name(name + ".ipl_good") + .desc("number of times we switched to this ipl from a different ipl") + .flags(total | pdf | nozero | nonan) + ; + + _iplTicks + .init(32) + .name(name + ".ipl_ticks") + .desc("number of cycles we spent at this ipl") + .flags(total | pdf | nozero | nonan) + ; + + _iplUsed + .name(name + ".ipl_used") + .desc("fraction of swpipl calls that actually changed the ipl") + .flags(total | nozero | nonan) + ; + + _iplUsed = _iplGood / _iplCount; + + _callpal + .init(256) + .name(name + ".callpal") + .desc("number of callpals executed") + .flags(total | pdf | nozero | nonan) + ; + + for (int i = 0; i < PAL::NumCodes; ++i) { + const char *str = PAL::name(i); + if (str) + _callpal.subname(i, str); + } + + _syscall + .init(SystemCalls::Number) + .name(name + ".syscall") + .desc("number of syscalls executed") + .flags(total | pdf | nozero | nonan) + ; + + for (int i = 0; i < SystemCalls::Number; ++i) { + const char *str = SystemCalls::name(i); + if (str) { + _syscall.subname(i, str); + } + } + + _faults + .init(Num_Faults) + .name(name + ".faults") + .desc("number of faults") + .flags(total | pdf | nozero | nonan) + ; + + for (int i = 1; i < Num_Faults; ++i) { + const char *str = FaultName(i); + if (str) + _faults.subname(i, str); + } + + _mode + .init(2) + .name(name + ".mode_switch") + .subname(0, "kernel") + .subname(1, "user") + .desc("number of protection mode switches") + ; + + _modeGood + .init(2) + ; + + _modeFraction + .name(name + ".mode_switch_good") + .subname(0, "kernel") + .subname(1, "user") + .desc("fraction of useful protection mode switches") + .flags(total) + ; + _modeFraction = _modeGood / _mode; + + _modeTicks + .init(2) + .name(name + ".mode_ticks") + .subname(0, "kernel") + .subname(1, "user") + .desc("number of ticks spent at the given mode") + .flags(pdf) + ; + + _swap_context + .name(name + ".swap_context") + .desc("number of times the context was actually changed") + ; +} + +void +KernelStats::arm() +{ data->_arm++; } + +void +KernelStats::quiesce() +{ data->_quiesce++; } + +void +KernelStats::ivlb() +{ data->_ivlb++; } + +void +KernelStats::ivle() +{ data->_ivle++; } + +void +KernelStats::hwrei() +{ data->_hwrei++; } + +void +KernelStats::fault(Fault fault) +{ data->_faults[fault]++; } + +void +KernelStats::swpipl(int ipl) +{ data->swpipl(ipl); } + +void +KernelStats::mode(bool user) +{ data->mode(user); } + +void +KernelStats::context(Addr old_pcbb, Addr new_pcbb) +{ data->_swap_context++; } + +void +KernelStats::callpal(int code) +{ data->callpal(code); } + + +void +KSData::swpipl(int ipl) +{ + assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n"); + + _iplCount[ipl]++; + + if (ipl == iplLast) + return; + + _iplGood[ipl]++; + _iplTicks[iplLast] += curTick - iplLastTick; + iplLastTick = curTick; + iplLast = ipl; +} + +void +KSData::mode(bool user) +{ + _mode[user]++; + if (user == lastUser) + return; + + _modeGood[user]++; + _modeTicks[lastUser] += curTick - lastModeTick; + + lastModeTick = curTick; + lastUser = user; + + if (xc->system->bin) { + if (!xc->swCtx || xc->swCtx->callStack.empty()) { + if (user) + xc->system->User->activate(); + else + xc->system->Kernel->activate(); + } + } +} + +void +KSData::callpal(int code) +{ + if (!PAL::name(code)) + return; + + _callpal[code]++; + + switch (code) { + case PAL::callsys: + { + int number = xc->regs.intRegFile[0]; + if (SystemCalls::validSyscallNumber(number)) { + int cvtnum = SystemCalls::convert(number); + _syscall[cvtnum]++; + } + } + break; + } + + if (code == PAL::swpctx) { + SWContext *out = xc->swCtx; + System *sys = xc->system; + if (!sys->bin) + return; + DPRINTF(TCPIP, "swpctx event\n"); + if (out) { + DPRINTF(TCPIP, "swapping context out with this stack!\n"); + xc->system->dumpState(xc); + Addr oldPCB = xc->regs.ipr[TheISA::IPR_PALtemp23]; + + if (out->callStack.empty()) { + DPRINTF(TCPIP, "but removing it, cuz empty!\n"); + SWContext *find = sys->findContext(oldPCB); + if (find) { + assert(sys->findContext(oldPCB) == out); + sys->remContext(oldPCB); + } + delete out; + } else { + DPRINTF(TCPIP, "switching out context with pcb %#x, top fn %s\n", + oldPCB, out->callStack.top()->name); + if (!sys->findContext(oldPCB)) { + if (!sys->addContext(oldPCB, out)) + panic("could not add context"); + } + } + } + + Addr newPCB = xc->regs.intRegFile[16]; + SWContext *in = sys->findContext(newPCB); + xc->swCtx = in; + + if (in) { + assert(!in->callStack.empty() && + "should not be switching in empty context"); + DPRINTF(TCPIP, "swapping context in with this callstack!\n"); + xc->system->dumpState(xc); + sys->remContext(newPCB); + fnCall *top = in->callStack.top(); + DPRINTF(TCPIP, "switching in to pcb %#x, %s\n", newPCB, top->name); + assert(top->myBin && "should not switch to context with no Bin"); + top->myBin->activate(); + } else { + sys->Kernel->activate(); + } + DPRINTF(TCPIP, "end swpctx\n"); + } +} diff --git a/kern/kernel_stats.hh b/kern/kernel_stats.hh new file mode 100644 index 0000000000..4974037623 --- /dev/null +++ b/kern/kernel_stats.hh @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __KERNEL_STATS_HH__ +#define __KERNEL_STATS_HH__ + +#include + +class KSData; +class ExecContext; +class BaseCPU; +enum Fault; + +class KernelStats +{ + private: + KSData *data; + + public: + KernelStats(ExecContext *_xc, BaseCPU *_cpu); + ~KernelStats(); + + void regStats(const std::string &name); + + void arm(); + void quiesce(); + void ivlb(); + void ivle(); + void hwrei(); + + void fault(Fault fault); + void swpipl(int ipl); + void mode(bool user); + void context(Addr old_pcbb, Addr new_pcbb); + void callpal(int code); +}; + +#endif // __KERNEL_STATS_HH__ From 5833a478543346ddbfe78f798343ebcaee0c5298 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Thu, 10 Jun 2004 01:05:03 -0400 Subject: [PATCH 08/19] forgot to remove these files --HG-- extra : convert_revision : 91723409e22f36622b99309a3af227ea0c382cc7 From 018e92e45e7d76511ad7e14644e2bbbc005eaa80 Mon Sep 17 00:00:00 2001 From: Erik Hallnor Date: Sun, 13 Jun 2004 05:52:28 -0400 Subject: [PATCH 09/19] Add some rewritten trace readers. --HG-- extra : convert_revision : 4a085c5d8526d1bf3f7155cda40002281c0c3d1b --- cpu/trace/reader/ibm_reader.cc | 120 ++++++++++++++++++++ cpu/trace/reader/ibm_reader.hh | 73 ++++++++++++ cpu/trace/reader/itx_reader.cc | 198 +++++++++++++++++++++++++++++++++ cpu/trace/reader/itx_reader.hh | 82 ++++++++++++++ 4 files changed, 473 insertions(+) create mode 100644 cpu/trace/reader/ibm_reader.cc create mode 100644 cpu/trace/reader/ibm_reader.hh create mode 100644 cpu/trace/reader/itx_reader.cc create mode 100644 cpu/trace/reader/itx_reader.hh diff --git a/cpu/trace/reader/ibm_reader.cc b/cpu/trace/reader/ibm_reader.cc new file mode 100644 index 0000000000..439931dba7 --- /dev/null +++ b/cpu/trace/reader/ibm_reader.cc @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of a IBM memory trace format reader. + */ +#include + +#include "cpu/trace/reader/ibm_reader.hh" +#include "sim/builder.hh" +#include "base/misc.hh" // for fatal + +using namespace std; + +IBMReader::IBMReader(const string &name, const string &filename) + : MemTraceReader(name) +{ + if (strcmp((filename.c_str() + filename.length() -3), ".gz") == 0) { + // Compressed file, need to use a pipe to gzip. + stringstream buf; + buf << "gzip -d -c " << filename << endl; + trace = popen(buf.str().c_str(), "r"); + } else { + trace = fopen(filename.c_str(), "rb"); + } + if (!trace) { + fatal("Can't open file %s", filename); + } +} + +Tick +IBMReader::getNextReq(MemReqPtr &req) +{ + MemReqPtr tmp_req; + + int c = getc(trace); + if (c != EOF) { + tmp_req = new MemReq(); + //int cpu_id = (c & 0xf0) >> 4; + int type = c & 0x0f; + // We have L1 miss traces, so all accesses are 128 bytes + tmp_req->size = 128; + + tmp_req->paddr = 0; + for (int i = 2; i >= 0; --i) { + c = getc(trace); + if (c == EOF) { + fatal("Unexpected end of file"); + } + tmp_req->paddr |= ((c & 0xff) << (8 * i)); + } + tmp_req->paddr = tmp_req->paddr << 7; + + switch(type) { + case IBM_COND_EXCLUSIVE_FETCH: + case IBM_READ_ONLY_FETCH: + tmp_req->cmd = Read; + break; + case IBM_EXCLUSIVE_FETCH: + case IBM_FETCH_NO_DATA: + tmp_req->cmd = Write; + break; + case IBM_INST_FETCH: + tmp_req->cmd = Read; + break; + default: + fatal("Unknown trace entry type."); + } + + } + req = tmp_req; + return 0; +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(IBMReader) + + Param filename; + +END_DECLARE_SIM_OBJECT_PARAMS(IBMReader) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(IBMReader) + + INIT_PARAM(filename, "trace file") + +END_INIT_SIM_OBJECT_PARAMS(IBMReader) + + +CREATE_SIM_OBJECT(IBMReader) +{ + return new IBMReader(getInstanceName(), filename); +} + +REGISTER_SIM_OBJECT("IBMReader", IBMReader) diff --git a/cpu/trace/reader/ibm_reader.hh b/cpu/trace/reader/ibm_reader.hh new file mode 100644 index 0000000000..0f14da24dd --- /dev/null +++ b/cpu/trace/reader/ibm_reader.hh @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Definition of a IBM memory trace format reader. + */ + +#ifndef __IBM_READER_HH__ +#define __IBM_READER_HH__ + +#include +#include "cpu/trace/reader/mem_trace_reader.hh" +#include "mem/mem_req.hh" + +/** + * A memory trace reader for the IBM memory trace format. + */ +class IBMReader : public MemTraceReader +{ + /** IBM trace file. */ + FILE* trace; + + enum IBMType { + IBM_INST_FETCH, + IBM_READ_ONLY_FETCH, + IBM_COND_EXCLUSIVE_FETCH, + IBM_EXCLUSIVE_FETCH, + IBM_FETCH_NO_DATA + }; + + public: + /** + * Construct an IBMReader. + */ + IBMReader(const std::string &name, const std::string &filename); + + /** + * Read the next request from the trace. Returns the request in the + * provided MemReqPtr and the cycle of the request in the return value. + * @param req Return the next request from the trace. + * @return IBM traces don't store timing information, return 0 + */ + virtual Tick getNextReq(MemReqPtr &req); +}; + +#endif //__IBM_READER_HH__ + diff --git a/cpu/trace/reader/itx_reader.cc b/cpu/trace/reader/itx_reader.cc new file mode 100644 index 0000000000..54bbbc4ea2 --- /dev/null +++ b/cpu/trace/reader/itx_reader.cc @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of a Intel ITX memory trace format reader. + */ +#include + +#include "cpu/trace/reader/itx_reader.hh" +#include "sim/builder.hh" +#include "base/misc.hh" // for fatal + +using namespace std; + +ITXReader::ITXReader(const string &name, const string &filename) + : MemTraceReader(name) +{ + if (strcmp((filename.c_str() + filename.length() -3), ".gz") == 0) { + // Compressed file, need to use a pipe to gzip. + stringstream buf; + buf << "gzip -d -c " << filename << endl; + trace = popen(buf.str().c_str(), "r"); + } else { + trace = fopen(filename.c_str(), "rb"); + } + if (!trace) { + fatal("Can't open file %s", filename); + } + traceFormat = 0; + int c; + for (int i = 0; i < 4; ++i) { + c = getc(trace); + if (c == EOF) { + fatal("Unexpected end of trace file."); + } + traceFormat |= (c & 0xff) << (8 * i); + } + if (traceFormat > 2) + fatal("Invalid trace format."); +} + +Tick +ITXReader::getNextReq(MemReqPtr &req) +{ + MemReqPtr tmp_req = new MemReq(); + bool phys_val; + do { + int c = getc(trace); + if (c != EOF) { + // Decode first byte + // phys_val<1> | type <2:0> | size <3:0> + phys_val = c & 0x80; + tmp_req->size = (c & 0x0f) + 1; + int type = (c & 0x70) >> 4; + + // Could be a compressed instruction entry, expand if necessary + if (type == ITXCodeComp) { + if (traceFormat != 2) { + fatal("Compressed code entry in non CompCode trace."); + } + if (!codeVirtValid) { + fatal("Corrupt CodeComp entry."); + } + + tmp_req->vaddr = codeVirtAddr; + codeVirtAddr += tmp_req->size; + if (phys_val) { + if (!codePhysValid) { + fatal("Corrupt CodeComp entry."); + } + tmp_req->paddr = codePhysAddr; + if (((tmp_req->paddr & 0xfff) + tmp_req->size) & ~0xfff) { + // Crossed page boundary, next physical address is + // invalid + codePhysValid = false; + } else { + codePhysAddr += tmp_req->size; + } + } else { + codePhysValid = false; + } + type = ITXCode; + tmp_req->cmd = Read; + } else { + // Normal entry + tmp_req->vaddr = 0; + for (int i = 0; i < 4; ++i) { + c = getc(trace); + if (c == EOF) { + fatal("Unexpected end of trace file."); + } + tmp_req->vaddr |= (c & 0xff) << (8 * i); + } + if (type == ITXCode) { + codeVirtAddr = tmp_req->vaddr + tmp_req->size; + codeVirtValid = true; + } + tmp_req->paddr = 0; + if (phys_val) { + c = getc(trace); + if (c == EOF) { + fatal("Unexpected end of trace file."); + } + // Get the page offset from the virtual address. + tmp_req->paddr = tmp_req->vaddr & 0xfff; + tmp_req->paddr |= (c & 0xf0) << 8; + for (int i = 2; i < 4; ++i) { + c = getc(trace); + if (c == EOF) { + fatal("Unexpected end of trace file."); + } + tmp_req->paddr |= (c & 0xff) << (8 * i); + } + if (type == ITXCode) { + if (((tmp_req->paddr & 0xfff) + tmp_req->size) + & ~0xfff) { + // Crossing the page boundary, next physical + // address isn't valid + codePhysValid = false; + } else { + codePhysAddr = tmp_req->paddr + tmp_req->size; + codePhysValid = true; + } + } + } else if (type == ITXCode) { + codePhysValid = false; + } + switch(type) { + case ITXRead: + tmp_req->cmd = Read; + break; + case ITXWrite: + tmp_req->cmd = Write; + break; + case ITXCode: + tmp_req->cmd = Read; + break; + default: + fatal("Unknown ITX type"); + } + } + } else { + // EOF need to return a null request + MemReqPtr null_req; + req = null_req; + return 0; + } + } while (!phys_val); + req = tmp_req; + return 0; +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITXReader) + + Param filename; + +END_DECLARE_SIM_OBJECT_PARAMS(ITXReader) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(ITXReader) + + INIT_PARAM(filename, "trace file") + +END_INIT_SIM_OBJECT_PARAMS(ITXReader) + + +CREATE_SIM_OBJECT(ITXReader) +{ + return new ITXReader(getInstanceName(), filename); +} + +REGISTER_SIM_OBJECT("ITXReader", ITXReader) diff --git a/cpu/trace/reader/itx_reader.hh b/cpu/trace/reader/itx_reader.hh new file mode 100644 index 0000000000..ff74062eae --- /dev/null +++ b/cpu/trace/reader/itx_reader.hh @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2003-2004 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Definition of a Intel ITX memory trace format reader. + */ + +#ifndef __ITX_READER_HH__ +#define __ITX_READER_HH__ + +#include + +#include "cpu/trace/reader/mem_trace_reader.hh" +#include "mem/mem_req.hh" + + +/** + * A memory trace reader for the Intel ITX memory trace format. + */ +class ITXReader : public MemTraceReader +{ + /** Trace file. */ + FILE *trace; + + bool codeVirtValid; + Addr codeVirtAddr; + bool codePhysValid; + Addr codePhysAddr; + + int traceFormat; + + enum ITXType { + ITXRead, + ITXWrite, + ITXWriteback, + ITXCode, + ITXCodeComp + }; + + public: + /** + * Construct an ITXReader. + */ + ITXReader(const std::string &name, const std::string &filename); + + /** + * Read the next request from the trace. Returns the request in the + * provided MemReqPtr and the cycle of the request in the return value. + * @param req Return the next request from the trace. + * @return ITX traces don't store timing information, return 0 + */ + virtual Tick getNextReq(MemReqPtr &req); +}; + +#endif //__ITX_READER_HH__ + From f6a06924b578d0eff04c81349e3a6a7737dce03c Mon Sep 17 00:00:00 2001 From: Erik Hallnor Date: Mon, 14 Jun 2004 00:45:30 -0400 Subject: [PATCH 10/19] Add fast writes (wh64) back to the cache. --HG-- extra : convert_revision : 48081c86da3f7959957e35f8ec868da55c68b5ce From 58fe84b6468f8157f096724a506885437d51c044 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 15 Jun 2004 10:58:41 -0400 Subject: [PATCH 11/19] Reconfigure ini files to match the default system that I'd like to use for future papers. Notable changes include a 3 level cache hierarchy, a bug fix in the main memory bandwidth and narrowing of the machine. --HG-- extra : convert_revision : db0da82b0adaa5fa3413354e6d36bff9e3bd37dc From d53c6c168afa7eafdf8c4fa10a10f835db25e3da Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 15 Jun 2004 10:48:08 -0700 Subject: [PATCH 12/19] Get software prefetching to work in full-system mode. Mostly a matter of keeping prefetches to invalid addrs from messing up VM IPRs. Also discovered that wh64s were not being treated as prefetches, when they really should be (for the most part, anyway). arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: - Get rid of intrlock flag for locking VM fault regs (a la EV5); instead, just don't update regs on VPTE loads (a la EV6). - Add NO_FAULT MemReq flag to indicate references that should not cause page faults (i.e., prefetches). arch/alpha/ev5.cc: - Get rid of intrlock flag for locking VM fault regs (a la EV5); instead, just don't update regs on VPTE loads (a la EV6). - Add Fault trace flag. arch/alpha/isa_desc: - Add NO_FAULT MemReq flag to indicate references that should not cause page faults (i.e., prefetches). - Mark wh64 as a "data prefetch" instruction so it gets controlled properly by the FullCPU data prefetch control switch. - Align wh64 EA in decoder so issue stage doesn't need to worry about it. arch/alpha/isa_traits.hh: - Get rid of intrlock flag for locking VM fault regs (a la EV5); instead, just don't update regs on VPTE loads (a la EV6). base/traceflags.py: - Add Fault trace flag. cpu/simple_cpu/simple_cpu.hh: - Pass MemReq flags to writeHint() operation. cpu/static_inst.hh: Update comment re: prefetches. --HG-- extra : convert_revision : 62e466b0f4c0ff9961796270fa2e371ec24bcbb6 --- arch/alpha/alpha_memory.cc | 47 ++++++++++++++++-------------------- arch/alpha/alpha_memory.hh | 2 +- arch/alpha/ev5.cc | 5 +--- arch/alpha/isa_desc | 11 +++++---- arch/alpha/isa_traits.hh | 1 - base/traceflags.py | 1 + cpu/simple_cpu/simple_cpu.hh | 2 +- cpu/static_inst.hh | 3 +-- 8 files changed, 32 insertions(+), 40 deletions(-) diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index 23815bf01b..58aa13b8fc 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -415,12 +415,19 @@ AlphaDTB::regStats() } void -AlphaDTB::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const +AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const { + ExecContext *xc = req->xc; + Addr vaddr = req->vaddr; uint64_t *ipr = xc->regs.ipr; - // set fault address and flags - if (!xc->misspeculating() && !xc->regs.intrlock) { + // Set fault address and flags. Even though we're modeling an + // EV5, we use the EV6 technique of not latching fault registers + // on VPTE loads (instead of locking the registers until IPR_VA is + // read, like the EV5). The EV6 approach is cleaner and seems to + // work with EV5 PAL code, but not the other way around. + if (!xc->misspeculating() + && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) { // set VA register with faulting address ipr[AlphaISA::IPR_VA] = vaddr; @@ -432,9 +439,6 @@ AlphaDTB::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const // set VA_FORM register with faulting formatted address ipr[AlphaISA::IPR_VA_FORM] = ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3); - - // lock these registers until the VA register is read - xc->regs.intrlock = true; } } @@ -459,10 +463,8 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const } else { // verify that this is a good virtual address if (!validVirtualAddress(req->vaddr)) { - fault(req->vaddr, - ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK | - MM_STAT_ACV_MASK), - req->xc); + fault(req, ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK | + MM_STAT_ACV_MASK)); if (write) { write_acv++; } else { read_acv++; } return DTB_Fault_Fault; @@ -476,9 +478,7 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const // only valid in kernel mode if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != AlphaISA::mode_kernel) { - fault(req->vaddr, - ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK), - req->xc); + fault(req, ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK)); if (write) { write_acv++; } else { read_acv++; } return DTB_Acv_Fault; } @@ -496,9 +496,8 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const if (!pte) { // page fault - fault(req->vaddr, - ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK), - req->xc); + fault(req, + (write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK); if (write) { write_misses++; } else { read_misses++; } return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault; } @@ -508,29 +507,25 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const if (write) { if (!(pte->xwe & MODE2MASK(mode))) { // declare the instruction access fault - fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_ACV_MASK | - (pte->fonw ? MM_STAT_FONW_MASK : 0), - req->xc); + fault(req, (MM_STAT_WR_MASK | MM_STAT_ACV_MASK | + (pte->fonw ? MM_STAT_FONW_MASK : 0))); write_acv++; return DTB_Fault_Fault; } if (pte->fonw) { - fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK, - req->xc); + fault(req, MM_STAT_WR_MASK | MM_STAT_FONW_MASK); write_acv++; return DTB_Fault_Fault; } } else { if (!(pte->xre & MODE2MASK(mode))) { - fault(req->vaddr, - MM_STAT_ACV_MASK | - (pte->fonr ? MM_STAT_FONR_MASK : 0), - req->xc); + fault(req, (MM_STAT_ACV_MASK | + (pte->fonr ? MM_STAT_FONR_MASK : 0))); read_acv++; return DTB_Acv_Fault; } if (pte->fonr) { - fault(req->vaddr, MM_STAT_FONR_MASK, req->xc); + fault(req, MM_STAT_FONR_MASK); read_acv++; return DTB_Fault_Fault; } diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh index b5fc182552..fbd6ecf155 100644 --- a/arch/alpha/alpha_memory.hh +++ b/arch/alpha/alpha_memory.hh @@ -112,7 +112,7 @@ class AlphaDTB : public AlphaTLB Stats::Formula accesses; protected: - void fault(Addr pc, uint64_t flags, ExecContext *xc) const; + void fault(MemReqPtr &req, uint64_t flags) const; public: AlphaDTB(const std::string &name, int size); diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index ecf66f4f51..d2ca71b3a0 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -162,6 +162,7 @@ AlphaISA::zeroRegisters(XC *xc) void ExecContext::ev5_trap(Fault fault) { + DPRINTF(Fault, "Fault %s\n", FaultName(fault)); Stats::recordEvent(csprintf("Fault %s", FaultName(fault))); assert(!misspeculating()); @@ -302,11 +303,7 @@ ExecContext::readIpr(int idx, Fault &fault) break; case AlphaISA::IPR_VA: - // SFX: unlocks interrupt status registers retval = ipr[idx]; - - if (!misspeculating()) - regs.intrlock = false; break; case AlphaISA::IPR_VA_FORM: diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc index 9fee124850..6c5912c528 100644 --- a/arch/alpha/isa_desc +++ b/arch/alpha/isa_desc @@ -1023,7 +1023,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '', # and memory access flags (handled here). # Would be nice to autogenerate this list, but oh well. - valid_mem_flags = ['LOCKED', 'EVICT_NEXT', 'PF_EXCLUSIVE'] + valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE'] inst_flags = [] mem_flags = [] for f in flags: @@ -1072,7 +1072,7 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{ # Declare the prefetch instruction object. # convert flags from tuple to list to make them mutable - pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp'] + pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT'] (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ LoadStoreBase(name, Name + 'Prefetch', ea_code, '', @@ -2369,9 +2369,10 @@ decode OPCODE default Unknown::unknown() { } format MiscPrefetch { - 0xf800: wh64({{ EA = Rb; }}, - {{ xc->writeHint(EA, 64); }}, - IsMemRef, IsStore, MemWriteOp); + 0xf800: wh64({{ EA = Rb & ~ULL(63); }}, + {{ xc->writeHint(EA, 64, memAccessFlags); }}, + IsMemRef, IsDataPrefetch, IsStore, MemWriteOp, + NO_FAULT); } format BasicOperate { diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh index 37ba77192b..1a8ff663b5 100644 --- a/arch/alpha/isa_traits.hh +++ b/arch/alpha/isa_traits.hh @@ -153,7 +153,6 @@ class AlphaISA #ifdef FULL_SYSTEM IntReg palregs[NumIntRegs]; // PAL shadow registers InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs - int intrlock; // interrupt register lock flag int intrflag; // interrupt flag bool pal_shadow; // using pal_shadow registers #endif // FULL_SYSTEM diff --git a/base/traceflags.py b/base/traceflags.py index 69f4e7ab85..a01eae3eb3 100644 --- a/base/traceflags.py +++ b/base/traceflags.py @@ -66,6 +66,7 @@ baseFlags = [ 'AlphaConsole', 'Flow', 'Interrupt', + 'Fault', 'Cycle', 'Loader', 'MMU', diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index 1c6b18d039..545c753f0a 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -253,7 +253,7 @@ class SimpleCPU : public BaseCPU // need to do this... } - void writeHint(Addr addr, int size) + void writeHint(Addr addr, int size, unsigned flags) { // need to do this... } diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index 3eeefb6756..68c30df2f6 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -72,8 +72,7 @@ class StaticInstBase : public RefCounted /// unconditional branches, memory barriers) or both (e.g., an /// FP/int conversion). /// - If IsMemRef is set, then exactly one of IsLoad or IsStore - /// will be set. Prefetches are marked as IsLoad, even if they - /// prefetch exclusive copies. + /// will be set. /// - If IsControl is set, then exactly one of IsDirectControl or /// IsIndirect Control will be set, and exactly one of /// IsCondControl or IsUncondControl will be set. From 35d125695c8c61df765b4adc983c9e0b41f69bd2 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 15 Jun 2004 17:08:34 -0400 Subject: [PATCH 13/19] Enable software prefetches in FullCPU by default. --HG-- extra : convert_revision : b492c3537b4ae443bfd2c4d8f17cebead389dfc6 From 4c2f38fadee01bd2d6fe9ca2f1c3c3976eef6688 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 21 Jun 2004 16:26:21 -0700 Subject: [PATCH 14/19] Record execution faults in DynInst fault field. Previously the DynInst field was being set only on memory faults. If an FP memory op encountered an FP enable fault, then the bogus memory op would still get processed since the pipeline relied on the inst->fault field to tell if the op was bogus. --HG-- extra : convert_revision : 7435d712a464ce71b518425e0580aa22822fb901 From 637f6813d2e995ab08e7d5f72e5b85edfa736075 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 21 Jun 2004 20:48:55 -0700 Subject: [PATCH 15/19] Don't put store prefetches (like wh64) with invalid addresses in the store buffer. --HG-- extra : convert_revision : c70cba4d5976b21967a53c7c728f2cbda1dfc183 From 800445f4b814d2c6acc92c68d8fc7dee0bf4f8ae Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 21 Jun 2004 22:39:59 -0700 Subject: [PATCH 16/19] Get rid of DynInst 'valid' hack check... bug it was put in for is long gone. --HG-- extra : convert_revision : ae2975894c9c4aeec65466ff9798a0420b4c7782 From c1e58b6bf6b353f9355aafd8ed2cb86e6d00e32a Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 21 Jun 2004 22:42:16 -0700 Subject: [PATCH 17/19] Handle SIGABRT a little more nicely. base/misc.cc: Don't dump trace in panic(), SIGABRT handler will do it now. sim/main.cc: Add SIGABRT handler that prints curTick and dumps buffered trace (if any). This doesn't work as well as I would like since the buffered trace records often contain stale references to stack-resident temporary std::string objects. Someday we'll have to put in a fix for that. --HG-- extra : convert_revision : 67576efbf5c10e63e255fc9a9ec520326fd3567b --- base/misc.cc | 5 ----- sim/main.cc | 13 +++++++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/base/misc.cc b/base/misc.cc index 5caf96d407..1304fb1282 100644 --- a/base/misc.cc +++ b/base/misc.cc @@ -61,11 +61,6 @@ __panic(const string &format, cp::ArgList &args, const char *func, delete &args; -#if TRACING_ON - // dump trace buffer, if there is one - Trace::theLog.dump(cerr); -#endif - abort(); } diff --git a/sim/main.cc b/sim/main.cc index 032a05668d..c990d830b7 100644 --- a/sim/main.cc +++ b/sim/main.cc @@ -90,6 +90,18 @@ exitNowHandler(int sigtype) async_exit = true; } +/// Abort signal handler. +void +abortHandler(int sigtype) +{ + cerr << "Program aborted at cycle " << curTick << endl; + +#if TRACING_ON + // dump trace buffer, if there is one + Trace::theLog.dump(cerr); +#endif +} + /// Simulator executable name const char *myProgName = ""; @@ -232,6 +244,7 @@ main(int argc, char **argv) signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats signal(SIGINT, exitNowHandler); // dump final stats and exit + signal(SIGABRT, abortHandler); sayHello(cerr); From b3ea4d90cf8d6c01f2a900798bbbeadf31bddac5 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 22 Jun 2004 13:49:26 -0400 Subject: [PATCH 18/19] pulled from head before pushing linux tree --HG-- extra : convert_revision : 27868e84419a4bc2b9abf59a813b8c8acb8c6083 From f37eb6f5c7184acb6df46d14d9e48a22c8ac8134 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 22 Jun 2004 17:20:19 -0400 Subject: [PATCH 19/19] ifdefed ev5 vs. ev6 differences so Tlaser can work in the linux tree arch/alpha/alpha_memory.cc: arch/alpha/ev5.hh: Ifdefed TLASER code arch/alpha/vtophys.cc: added back some code andrew removed and couldn't remember why. --HG-- extra : convert_revision : f00d255f7a8a7bdb6e74f061dd014188e3b39e73 --- arch/alpha/alpha_memory.cc | 47 +++++++++++++++++++++++++++++++------- arch/alpha/ev5.hh | 31 ++++++++++++++++++++----- arch/alpha/vtophys.cc | 15 +++++++----- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index f8be89cbe3..a40ad7a5c8 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -101,18 +101,34 @@ AlphaTLB::checkCacheability(MemReqPtr &req) * to catch a weird case where both are used, which shouldn't happen. */ + +#ifdef ALPHA_TLASER + if (req->paddr & PA_UNCACHED_BIT_39) { +#else if (req->paddr & PA_UNCACHED_BIT_43) { +#endif // IPR memory space not implemented - if (PA_IPR_SPACE(req->paddr)) - if (!req->xc->misspeculating()) - panic("IPR memory space not implemented! PA=%x\n", - req->paddr); + if (PA_IPR_SPACE(req->paddr)) { + if (!req->xc->misspeculating()) { + switch (req->paddr) { + case ULL(0xFFFFF00188): + req->data = 0; + break; - // mark request as uncacheable - req->flags |= UNCACHEABLE; + default: + panic("IPR memory space not implemented! PA=%x\n", + req->paddr); + } + } + } else { + // mark request as uncacheable + req->flags |= UNCACHEABLE; - // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) - req->paddr &= PA_UNCACHED_MASK; +#ifndef ALPHA_TLASER + // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) + req->paddr &= PA_UNCACHED_MASK; +#endif + } } } @@ -301,7 +317,13 @@ AlphaITB::translate(MemReqPtr &req) const // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5 // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 +#ifdef ALPHA_TLASER + if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && + VA_SPACE_EV5(req->vaddr) == 2) { +#else if (VA_SPACE_EV6(req->vaddr) == 0x7e) { +#endif + // only valid in kernel mode if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) { @@ -312,11 +334,13 @@ AlphaITB::translate(MemReqPtr &req) const req->paddr = req->vaddr & PA_IMPL_MASK; +#ifndef ALPHA_TLASER // sign extend the physical address properly if (req->paddr & PA_UNCACHED_BIT_40) req->paddr |= ULL(0xf0000000000); else req->paddr &= ULL(0xffffffffff); +#endif } else { // not a physical address: need to look up pte @@ -486,7 +510,12 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const } // Check for "superpage" mapping +#ifdef ALPHA_TLASER + if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && + VA_SPACE_EV5(req->vaddr) == 2) { +#else if (VA_SPACE_EV6(req->vaddr) == 0x7e) { +#endif // only valid in kernel mode if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != @@ -498,11 +527,13 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const req->paddr = req->vaddr & PA_IMPL_MASK; +#ifndef ALPHA_TLASER // sign extend the physical address properly if (req->paddr & PA_UNCACHED_BIT_40) req->paddr |= ULL(0xf0000000000); else req->paddr &= ULL(0xffffffffff); +#endif } else { if (write) diff --git a/arch/alpha/ev5.hh b/arch/alpha/ev5.hh index 517e1111f0..5b27dd3dcd 100644 --- a/arch/alpha/ev5.hh +++ b/arch/alpha/ev5.hh @@ -32,8 +32,15 @@ #define ALT_MODE_AM(X) (((X) >> 3) & 0x3) #define DTB_CM_CM(X) (((X) >> 3) & 0x3) + +#ifdef ALPHA_TLASER +#define DTB_ASN_ASN(X) (((X) >> 57) & 0x7f) +#define DTB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff) +#else #define DTB_ASN_ASN(X) (((X) >> 57) & 0xff) #define DTB_PTE_PPN(X) (((X) >> 32) & 0x07fffffff) +#endif + #define DTB_PTE_XRE(X) (((X) >> 8) & 0xf) #define DTB_PTE_XWE(X) (((X) >> 12) & 0xf) #define DTB_PTE_FONR(X) (((X) >> 1) & 0x1) @@ -41,9 +48,16 @@ #define DTB_PTE_GH(X) (((X) >> 5) & 0x3) #define DTB_PTE_ASMA(X) (((X) >> 4) & 0x1) -#define ICM_CM(X) (((X) >> 3) & 0x3) +#define ICM_CM(X) (((X) >> 3) & 0x3) + +#ifdef ALPHA_TLASER +#define ITB_ASN_ASN(X) (((X) >> 4) & 0x7f) +#define ITB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff) +#else #define ITB_ASN_ASN(X) (((X) >> 4) & 0xff) #define ITB_PTE_PPN(X) (((X) >> 32) & 0x07fffffff) +#endif + #define ITB_PTE_XRE(X) (((X) >> 8) & 0xf) #define ITB_PTE_FONR(X) (((X) >> 1) & 0x1) #define ITB_PTE_FONW(X) (((X) >> 2) & 0x1) @@ -52,18 +66,23 @@ #define VA_UNIMPL_MASK ULL(0xfffff80000000000) #define VA_IMPL_MASK ULL(0x000007ffffffffff) -#define VA_IMPL(X) ((X) & VA_IMPL_MASK) -#define VA_VPN(X) (VA_IMPL(X) >> 13) +#define VA_IMPL(X) ((X) & VA_IMPL_MASK) +#define VA_VPN(X) (VA_IMPL(X) >> 13) #define VA_SPACE_EV5(X) (((X) >> 41) & 0x3) -#define VA_SPACE_EV6(X) (((X) >> 41) & 0x7f) -#define VA_POFS(X) ((X) & 0x1fff) +#define VA_SPACE_EV6(X) (((X) >> 41) & 0x7f) +#define VA_POFS(X) ((X) & 0x1fff) -#define PA_IMPL_MASK ULL(0xfffffffffff) // for Tsunami #define PA_UNCACHED_BIT_39 ULL(0x8000000000) #define PA_UNCACHED_BIT_40 ULL(0x10000000000) #define PA_UNCACHED_BIT_43 ULL(0x80000000000) #define PA_UNCACHED_MASK ULL(0x807ffffffff) // Clear PA<42:35> +#ifdef ALPHA_TLASER +#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFF00000)) +#define PA_IMPL_MASK ULL(0xffffffffff) +#else #define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFFF00000)) +#define PA_IMPL_MASK ULL(0xfffffffffff) // for Tsunami +#endif #define PA_PFN2PA(X) ((X) << 13) diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc index cf2ebbf803..7a38b296b9 100644 --- a/arch/alpha/vtophys.cc +++ b/arch/alpha/vtophys.cc @@ -96,20 +96,23 @@ vtophys(ExecContext *xc, Addr vaddr) { Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20]; Addr paddr = 0; -// if (PC_PAL(vaddr)) { -// paddr = vaddr & ~ULL(1); -// } else { + //@todo Andrew couldn't remember why he commented some of this code + //so I put it back in. Perhaps something to do with gdb debugging? + if (PC_PAL(vaddr)) { + paddr = vaddr & ~ULL(1); + } else if (!ptbr) { + paddr = vaddr; + } else { if (vaddr >= ALPHA_K0SEG_BASE && vaddr <= ALPHA_K0SEG_END) { paddr = ALPHA_K0SEG_TO_PHYS(vaddr); - } else if (!ptbr) { - paddr = vaddr; } else { Addr pte = kernel_pte_lookup(xc->physmem, ptbr, vaddr); uint64_t entry = xc->physmem->phys_read_qword(pte); if (pte && entry_valid(entry)) paddr = PMAP_PTE_PA(entry) | (vaddr & PGOFSET); } -// } + } + DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);