CacheRecorder.cc revision 10302
16145SN/A/* 28683SN/A * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood 38683SN/A * Copyright (c) 2010 Advanced Micro Devices, Inc. 46145SN/A * All rights reserved. 56145SN/A * 66145SN/A * Redistribution and use in source and binary forms, with or without 76145SN/A * modification, are permitted provided that the following conditions are 86145SN/A * met: redistributions of source code must retain the above copyright 96145SN/A * notice, this list of conditions and the following disclaimer; 106145SN/A * redistributions in binary form must reproduce the above copyright 116145SN/A * notice, this list of conditions and the following disclaimer in the 126145SN/A * documentation and/or other materials provided with the distribution; 136145SN/A * neither the name of the copyright holders nor the names of its 146145SN/A * contributors may be used to endorse or promote products derived from 156145SN/A * this software without specific prior written permission. 166145SN/A * 176145SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186145SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196145SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206145SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216145SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226145SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236145SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246145SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256145SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266145SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276145SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286145SN/A */ 296145SN/A 308683SN/A#include "debug/RubyCacheTrace.hh" 3110301Snilay@cs.wisc.edu#include "mem/ruby/system/CacheRecorder.hh" 328683SN/A#include "mem/ruby/system/Sequencer.hh" 338683SN/A#include "mem/ruby/system/System.hh" 346145SN/A 357055SN/Ausing namespace std; 367055SN/A 377054SN/Avoid 388683SN/ATraceRecord::print(ostream& out) const 396145SN/A{ 408683SN/A out << "[TraceRecord: Node, " << m_cntrl_id << ", " 418683SN/A << m_data_address << ", " << m_pc_address << ", " 428683SN/A << m_type << ", Time: " << m_time << "]"; 438683SN/A} 448683SN/A 458683SN/ACacheRecorder::CacheRecorder() 468683SN/A : m_uncompressed_trace(NULL), 4710163SN/A m_uncompressed_trace_size(0), 4810163SN/A m_block_size_bytes(RubySystem::getBlockSizeBytes()) 498683SN/A{ 508683SN/A} 518683SN/A 528683SN/ACacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, 538683SN/A uint64_t uncompressed_trace_size, 5410163SN/A std::vector<Sequencer*>& seq_map, 5510163SN/A uint64_t block_size_bytes) 568683SN/A : m_uncompressed_trace(uncompressed_trace), 578683SN/A m_uncompressed_trace_size(uncompressed_trace_size), 588683SN/A m_seq_map(seq_map), m_bytes_read(0), m_records_read(0), 5910163SN/A m_records_flushed(0), m_block_size_bytes(block_size_bytes) 608683SN/A{ 6110163SN/A if (m_uncompressed_trace != NULL) { 6210163SN/A if (m_block_size_bytes < RubySystem::getBlockSizeBytes()) { 6310163SN/A // Block sizes larger than when the trace was recorded are not 6410163SN/A // supported, as we cannot reliably turn accesses to smaller blocks 6510163SN/A // into larger ones. 6610163SN/A panic("Recorded cache block size (%d) < current block size (%d) !!", 6710163SN/A m_block_size_bytes, RubySystem::getBlockSizeBytes()); 6810163SN/A } 6910163SN/A } 708683SN/A} 718683SN/A 728683SN/ACacheRecorder::~CacheRecorder() 738683SN/A{ 748683SN/A if (m_uncompressed_trace != NULL) { 759627SN/A delete [] m_uncompressed_trace; 768683SN/A m_uncompressed_trace = NULL; 778683SN/A } 788683SN/A m_seq_map.clear(); 798683SN/A} 808683SN/A 818683SN/Avoid 828683SN/ACacheRecorder::enqueueNextFlushRequest() 838683SN/A{ 848683SN/A if (m_records_flushed < m_records.size()) { 858683SN/A TraceRecord* rec = m_records[m_records_flushed]; 868683SN/A m_records_flushed++; 878683SN/A Request* req = new Request(rec->m_data_address, 8810163SN/A m_block_size_bytes, 0, 898832SN/A Request::funcMasterId); 908683SN/A MemCmd::Command requestType = MemCmd::FlushReq; 918949SN/A Packet *pkt = new Packet(req, requestType); 928683SN/A 938683SN/A Sequencer* m_sequencer_ptr = m_seq_map[rec->m_cntrl_id]; 948683SN/A assert(m_sequencer_ptr != NULL); 958683SN/A m_sequencer_ptr->makeRequest(pkt); 968683SN/A 978683SN/A DPRINTF(RubyCacheTrace, "Flushing %s\n", *rec); 988683SN/A } 998683SN/A} 1008683SN/A 1018683SN/Avoid 1028683SN/ACacheRecorder::enqueueNextFetchRequest() 1038683SN/A{ 1048683SN/A if (m_bytes_read < m_uncompressed_trace_size) { 1058683SN/A TraceRecord* traceRecord = (TraceRecord*) (m_uncompressed_trace + 1068683SN/A m_bytes_read); 1078683SN/A 1088683SN/A DPRINTF(RubyCacheTrace, "Issuing %s\n", *traceRecord); 1098683SN/A 11010163SN/A for (int rec_bytes_read = 0; rec_bytes_read < m_block_size_bytes; 11110163SN/A rec_bytes_read += RubySystem::getBlockSizeBytes()) { 11210163SN/A Request* req = new Request(); 11310163SN/A MemCmd::Command requestType; 11410163SN/A 11510163SN/A if (traceRecord->m_type == RubyRequestType_LD) { 11610163SN/A requestType = MemCmd::ReadReq; 11710163SN/A req->setPhys(traceRecord->m_data_address + rec_bytes_read, 11810163SN/A RubySystem::getBlockSizeBytes(), 0, Request::funcMasterId); 11910163SN/A } else if (traceRecord->m_type == RubyRequestType_IFETCH) { 12010163SN/A requestType = MemCmd::ReadReq; 12110163SN/A req->setPhys(traceRecord->m_data_address + rec_bytes_read, 12210163SN/A RubySystem::getBlockSizeBytes(), 12310163SN/A Request::INST_FETCH, Request::funcMasterId); 12410163SN/A } else { 12510163SN/A requestType = MemCmd::WriteReq; 12610163SN/A req->setPhys(traceRecord->m_data_address + rec_bytes_read, 12710163SN/A RubySystem::getBlockSizeBytes(), 0, Request::funcMasterId); 12810163SN/A } 12910163SN/A 13010163SN/A Packet *pkt = new Packet(req, requestType); 13110163SN/A pkt->dataStatic(traceRecord->m_data + rec_bytes_read); 13210163SN/A 13310163SN/A Sequencer* m_sequencer_ptr = m_seq_map[traceRecord->m_cntrl_id]; 13410163SN/A assert(m_sequencer_ptr != NULL); 13510163SN/A m_sequencer_ptr->makeRequest(pkt); 1368683SN/A } 1378683SN/A 13810163SN/A m_bytes_read += (sizeof(TraceRecord) + m_block_size_bytes); 1398683SN/A m_records_read++; 1408683SN/A } 1418683SN/A} 1428683SN/A 1438683SN/Avoid 1448683SN/ACacheRecorder::addRecord(int cntrl, const physical_address_t data_addr, 1458683SN/A const physical_address_t pc_addr, 14610302Snilay@cs.wisc.edu RubyRequestType type, Tick time, DataBlock& data) 1478683SN/A{ 1488683SN/A TraceRecord* rec = (TraceRecord*)malloc(sizeof(TraceRecord) + 14910163SN/A m_block_size_bytes); 1508683SN/A rec->m_cntrl_id = cntrl; 1518683SN/A rec->m_time = time; 1528683SN/A rec->m_data_address = data_addr; 1538683SN/A rec->m_pc_address = pc_addr; 1548683SN/A rec->m_type = type; 15510163SN/A memcpy(rec->m_data, data.getData(0, m_block_size_bytes), 15610163SN/A m_block_size_bytes); 1578683SN/A 1587456SN/A m_records.push_back(rec); 1596145SN/A} 1606145SN/A 1618683SN/Auint64 1628683SN/ACacheRecorder::aggregateRecords(uint8_t** buf, uint64 total_size) 1636145SN/A{ 1648683SN/A std::sort(m_records.begin(), m_records.end(), compareTraceRecords); 1658683SN/A 1668683SN/A int size = m_records.size(); 1678683SN/A uint64 current_size = 0; 16810163SN/A int record_size = sizeof(TraceRecord) + m_block_size_bytes; 1698683SN/A 1708683SN/A for (int i = 0; i < size; ++i) { 1718683SN/A // Determine if we need to expand the buffer size 1728683SN/A if (current_size + record_size > total_size) { 1738683SN/A uint8_t* new_buf = new (nothrow) uint8_t[total_size * 2]; 1748683SN/A if (new_buf == NULL) { 1758683SN/A fatal("Unable to allocate buffer of size %s\n", 1768683SN/A total_size * 2); 1778683SN/A } 1788683SN/A total_size = total_size * 2; 1798683SN/A uint8_t* old_buf = *buf; 1808683SN/A memcpy(new_buf, old_buf, current_size); 1818683SN/A *buf = new_buf; 1828683SN/A delete [] old_buf; 1838683SN/A } 1848683SN/A 1858683SN/A // Copy the current record into the buffer 1868683SN/A memcpy(&((*buf)[current_size]), m_records[i], record_size); 1878683SN/A current_size += record_size; 1888683SN/A 1898683SN/A free(m_records[i]); 1908683SN/A m_records[i] = NULL; 1917054SN/A } 1926145SN/A 1937456SN/A m_records.clear(); 1948683SN/A return current_size; 1956145SN/A} 196