summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mem/SConscript3
-rw-r--r--src/mem/ruby/recorder/CacheRecorder.cc156
-rw-r--r--src/mem/ruby/recorder/CacheRecorder.hh80
-rw-r--r--src/mem/ruby/recorder/SConscript1
-rw-r--r--src/mem/ruby/recorder/TraceRecord.cc139
-rw-r--r--src/mem/ruby/recorder/TraceRecord.hh91
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.hh5
-rw-r--r--src/mem/ruby/system/CacheMemory.cc49
-rw-r--r--src/mem/ruby/system/CacheMemory.hh16
-rw-r--r--src/mem/slicc/symbols/StateMachine.py31
10 files changed, 270 insertions, 301 deletions
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 <algorithm>
-
-#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<Sequencer*>& 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<TraceRecord>());
+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 <iostream>
-#include <string>
#include <vector>
+#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<Sequencer*>& 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<TraceRecord> m_records;
+ std::vector<TraceRecord*> m_records;
+ uint8_t* m_uncompressed_trace;
+ uint64_t m_uncompressed_trace_size;
+ std::vector<Sequencer*> 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 <iostream>
-
-#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 <string>
#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 <vector>
#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: