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 3011793Sbrandon.potter@amd.com#include "mem/ruby/system/CacheRecorder.hh" 3111793Sbrandon.potter@amd.com 328683SN/A#include "debug/RubyCacheTrace.hh" 3311108Sdavid.hashe@amd.com#include "mem/ruby/system/RubySystem.hh" 348683SN/A#include "mem/ruby/system/Sequencer.hh" 356145SN/A 367055SN/Ausing namespace std; 377055SN/A 387054SN/Avoid 398683SN/ATraceRecord::print(ostream& out) const 406145SN/A{ 418683SN/A out << "[TraceRecord: Node, " << m_cntrl_id << ", " 428683SN/A << m_data_address << ", " << m_pc_address << ", " 438683SN/A << m_type << ", Time: " << m_time << "]"; 448683SN/A} 458683SN/A 468683SN/ACacheRecorder::CacheRecorder() 478683SN/A : m_uncompressed_trace(NULL), 4810163SN/A m_uncompressed_trace_size(0), 4910163SN/A m_block_size_bytes(RubySystem::getBlockSizeBytes()) 508683SN/A{ 518683SN/A} 528683SN/A 538683SN/ACacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, 548683SN/A uint64_t uncompressed_trace_size, 5510163SN/A std::vector<Sequencer*>& seq_map, 5610163SN/A uint64_t block_size_bytes) 578683SN/A : m_uncompressed_trace(uncompressed_trace), 588683SN/A m_uncompressed_trace_size(uncompressed_trace_size), 598683SN/A m_seq_map(seq_map), m_bytes_read(0), m_records_read(0), 6010163SN/A m_records_flushed(0), m_block_size_bytes(block_size_bytes) 618683SN/A{ 6211049Snilay@cs.wisc.edu if (m_uncompressed_trace != NULL) { 6311049Snilay@cs.wisc.edu if (m_block_size_bytes < RubySystem::getBlockSizeBytes()) { 6411049Snilay@cs.wisc.edu // Block sizes larger than when the trace was recorded are not 6511049Snilay@cs.wisc.edu // supported, as we cannot reliably turn accesses to smaller blocks 6611049Snilay@cs.wisc.edu // into larger ones. 6711049Snilay@cs.wisc.edu panic("Recorded cache block size (%d) < current block size (%d) !!", 6811049Snilay@cs.wisc.edu m_block_size_bytes, RubySystem::getBlockSizeBytes()); 6911049Snilay@cs.wisc.edu } 7011049Snilay@cs.wisc.edu } 718683SN/A} 728683SN/A 738683SN/ACacheRecorder::~CacheRecorder() 748683SN/A{ 758683SN/A if (m_uncompressed_trace != NULL) { 769627SN/A delete [] m_uncompressed_trace; 778683SN/A m_uncompressed_trace = NULL; 788683SN/A } 798683SN/A m_seq_map.clear(); 808683SN/A} 818683SN/A 828683SN/Avoid 838683SN/ACacheRecorder::enqueueNextFlushRequest() 848683SN/A{ 858683SN/A if (m_records_flushed < m_records.size()) { 868683SN/A TraceRecord* rec = m_records[m_records_flushed]; 878683SN/A m_records_flushed++; 8812749Sgiacomo.travaglini@arm.com auto req = std::make_shared<Request>(rec->m_data_address, 8912749Sgiacomo.travaglini@arm.com m_block_size_bytes, 0, 9012749Sgiacomo.travaglini@arm.com Request::funcMasterId); 918683SN/A MemCmd::Command requestType = MemCmd::FlushReq; 928949SN/A Packet *pkt = new Packet(req, requestType); 938683SN/A 948683SN/A Sequencer* m_sequencer_ptr = m_seq_map[rec->m_cntrl_id]; 958683SN/A assert(m_sequencer_ptr != NULL); 968683SN/A m_sequencer_ptr->makeRequest(pkt); 978683SN/A 988683SN/A DPRINTF(RubyCacheTrace, "Flushing %s\n", *rec); 9910991Stimothy.jones@cl.cam.ac.uk } else { 10010991Stimothy.jones@cl.cam.ac.uk DPRINTF(RubyCacheTrace, "Flushed all %d records\n", m_records_flushed); 1018683SN/A } 1028683SN/A} 1038683SN/A 1048683SN/Avoid 1058683SN/ACacheRecorder::enqueueNextFetchRequest() 1068683SN/A{ 1078683SN/A if (m_bytes_read < m_uncompressed_trace_size) { 1088683SN/A TraceRecord* traceRecord = (TraceRecord*) (m_uncompressed_trace + 1098683SN/A m_bytes_read); 1108683SN/A 1118683SN/A DPRINTF(RubyCacheTrace, "Issuing %s\n", *traceRecord); 1128683SN/A 11310163SN/A for (int rec_bytes_read = 0; rec_bytes_read < m_block_size_bytes; 11410163SN/A rec_bytes_read += RubySystem::getBlockSizeBytes()) { 11512749Sgiacomo.travaglini@arm.com RequestPtr req; 11610163SN/A MemCmd::Command requestType; 11710163SN/A 11810163SN/A if (traceRecord->m_type == RubyRequestType_LD) { 11910163SN/A requestType = MemCmd::ReadReq; 12012749Sgiacomo.travaglini@arm.com req = std::make_shared<Request>( 12112749Sgiacomo.travaglini@arm.com traceRecord->m_data_address + rec_bytes_read, 12210163SN/A RubySystem::getBlockSizeBytes(), 0, Request::funcMasterId); 12310163SN/A } else if (traceRecord->m_type == RubyRequestType_IFETCH) { 12410163SN/A requestType = MemCmd::ReadReq; 12512749Sgiacomo.travaglini@arm.com req = std::make_shared<Request>( 12612749Sgiacomo.travaglini@arm.com traceRecord->m_data_address + rec_bytes_read, 12710163SN/A RubySystem::getBlockSizeBytes(), 12810163SN/A Request::INST_FETCH, Request::funcMasterId); 12910163SN/A } else { 13010163SN/A requestType = MemCmd::WriteReq; 13112749Sgiacomo.travaglini@arm.com req = std::make_shared<Request>( 13212749Sgiacomo.travaglini@arm.com traceRecord->m_data_address + rec_bytes_read, 13310163SN/A RubySystem::getBlockSizeBytes(), 0, Request::funcMasterId); 13410163SN/A } 13510163SN/A 13610163SN/A Packet *pkt = new Packet(req, requestType); 13710163SN/A pkt->dataStatic(traceRecord->m_data + rec_bytes_read); 13810163SN/A 13910163SN/A Sequencer* m_sequencer_ptr = m_seq_map[traceRecord->m_cntrl_id]; 14010163SN/A assert(m_sequencer_ptr != NULL); 14110163SN/A m_sequencer_ptr->makeRequest(pkt); 1428683SN/A } 1438683SN/A 14410163SN/A m_bytes_read += (sizeof(TraceRecord) + m_block_size_bytes); 1458683SN/A m_records_read++; 14610991Stimothy.jones@cl.cam.ac.uk } else { 14710991Stimothy.jones@cl.cam.ac.uk DPRINTF(RubyCacheTrace, "Fetched all %d records\n", m_records_read); 1488683SN/A } 1498683SN/A} 1508683SN/A 1518683SN/Avoid 15211025Snilay@cs.wisc.eduCacheRecorder::addRecord(int cntrl, Addr data_addr, Addr pc_addr, 15310302Snilay@cs.wisc.edu RubyRequestType type, Tick time, DataBlock& data) 1548683SN/A{ 1558683SN/A TraceRecord* rec = (TraceRecord*)malloc(sizeof(TraceRecord) + 15610163SN/A m_block_size_bytes); 1578683SN/A rec->m_cntrl_id = cntrl; 1588683SN/A rec->m_time = time; 1598683SN/A rec->m_data_address = data_addr; 1608683SN/A rec->m_pc_address = pc_addr; 1618683SN/A rec->m_type = type; 16210163SN/A memcpy(rec->m_data, data.getData(0, m_block_size_bytes), 16310163SN/A m_block_size_bytes); 1648683SN/A 1657456SN/A m_records.push_back(rec); 1666145SN/A} 1676145SN/A 16811061Snilay@cs.wisc.eduuint64_t 16911061Snilay@cs.wisc.eduCacheRecorder::aggregateRecords(uint8_t **buf, uint64_t total_size) 1706145SN/A{ 1718683SN/A std::sort(m_records.begin(), m_records.end(), compareTraceRecords); 1728683SN/A 1738683SN/A int size = m_records.size(); 17411061Snilay@cs.wisc.edu uint64_t current_size = 0; 17510163SN/A int record_size = sizeof(TraceRecord) + m_block_size_bytes; 1768683SN/A 1778683SN/A for (int i = 0; i < size; ++i) { 1788683SN/A // Determine if we need to expand the buffer size 1798683SN/A if (current_size + record_size > total_size) { 1808683SN/A uint8_t* new_buf = new (nothrow) uint8_t[total_size * 2]; 1818683SN/A if (new_buf == NULL) { 1828683SN/A fatal("Unable to allocate buffer of size %s\n", 1838683SN/A total_size * 2); 1848683SN/A } 1858683SN/A total_size = total_size * 2; 1868683SN/A uint8_t* old_buf = *buf; 1878683SN/A memcpy(new_buf, old_buf, current_size); 1888683SN/A *buf = new_buf; 1898683SN/A delete [] old_buf; 1908683SN/A } 1918683SN/A 1928683SN/A // Copy the current record into the buffer 1938683SN/A memcpy(&((*buf)[current_size]), m_records[i], record_size); 1948683SN/A current_size += record_size; 1958683SN/A 1968683SN/A free(m_records[i]); 1978683SN/A m_records[i] = NULL; 1987054SN/A } 1996145SN/A 2007456SN/A m_records.clear(); 2018683SN/A return current_size; 2026145SN/A} 203