1 /*! 2 * \file trc_mem_acc_cache.cpp 3 * \brief OpenCSD : Memory accessor cache. 4 * 5 * \copyright Copyright (c) 2018, ARM Limited. All Rights Reserved. 6 */ 7 8 /* 9 * Redistribution and use in source and binary forms, with or without modification, 10 * are permitted provided that the following conditions are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the copyright holder nor the names of its contributors 20 * may be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <cstring> 36 #include <sstream> 37 #include <iomanip> 38 #include "mem_acc/trc_mem_acc_cache.h" 39 #include "mem_acc/trc_mem_acc_base.h" 40 #include "interfaces/trc_error_log_i.h" 41 42 #ifdef LOG_CACHE_STATS 43 #define INC_HITS_RL(idx) m_hits++; m_hit_rl[m_mru_idx]++; 44 #define INC_MISS() m_misses++; 45 #define INC_PAGES() m_pages++; 46 #define SET_MAX_RL(idx) \ 47 { \ 48 if (m_hit_rl_max[idx] < m_hit_rl[idx]) \ 49 m_hit_rl_max[idx] = m_hit_rl[idx]; \ 50 m_hit_rl[idx] = 0; \ 51 } 52 #define INC_RL(idx) m_hit_rl[m_mru_idx]++; 53 #else 54 #define INC_HITS_RL(idx) 55 #define INC_MISS() 56 #define INC_PAGES() 57 #define SET_MAX_RL(idx) 58 #define INC_RL(idx) 59 #endif 60 61 // uncomment to log cache ops 62 //#define LOG_CACHE_OPS 63 readBytesFromCache(TrcMemAccessorBase * p_accessor,const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t trcID,uint32_t * numBytes,uint8_t * byteBuffer)64 ocsd_err_t TrcMemAccCache::readBytesFromCache(TrcMemAccessorBase *p_accessor, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t trcID, uint32_t *numBytes, uint8_t *byteBuffer) 65 { 66 uint32_t bytesRead = 0, reqBytes = *numBytes; 67 ocsd_err_t err = OCSD_OK; 68 69 #ifdef LOG_CACHE_OPS 70 std::ostringstream oss; 71 #endif 72 73 if (m_bCacheEnabled) 74 { 75 if (blockInCache(address, reqBytes)) 76 { 77 bytesRead = reqBytes; 78 memcpy(byteBuffer, &m_mru[m_mru_idx].data[address - m_mru[m_mru_idx].st_addr], reqBytes); 79 #ifdef LOG_CACHE_OPS 80 oss << "TrcMemAccCache:: hit [page: " << std::dec << m_mru_idx << "[addr:0x" << std::hex << address << ", bytes: " << std::dec << reqBytes << "]\n"; 81 logMsg(oss.str()); 82 #endif 83 INC_HITS_RL(m_mru_idx); 84 } 85 else 86 { 87 INC_MISS(); 88 #ifdef LOG_CACHE_OPS 89 oss << "TrcMemAccCache:: miss [addr:0x" << std::hex << address << ", bytes: " << std::dec << reqBytes << "]\n"; 90 logMsg(oss.str()); 91 #endif 92 /* need a new cache page - check the underlying accessor for the data */ 93 m_mru_idx = m_mru_next_new; 94 m_mru[m_mru_idx].valid_len = p_accessor->readBytes(address, mem_space, trcID, MEM_ACC_CACHE_PAGE_SIZE, &m_mru[m_mru_idx].data[0]); 95 96 /* check return length valid - v bad if return length more than request */ 97 if (m_mru[m_mru_idx].valid_len > MEM_ACC_CACHE_PAGE_SIZE) 98 { 99 m_mru[m_mru_idx].valid_len = 0; // set to nothing returned. 100 err = OCSD_ERR_MEM_ACC_BAD_LEN; 101 } 102 103 if (m_mru[m_mru_idx].valid_len > 0) 104 { 105 // got some data - so save the 106 m_mru[m_mru_idx].st_addr = address; 107 108 // log the run length hit counts 109 SET_MAX_RL(m_mru_idx); 110 111 #ifdef LOG_CACHE_OPS 112 oss.str(""); 113 oss << "TrcMemAccCache:: load [page: " << std::dec << m_mru_idx << "[addr:0x" << std::hex << address << ", bytes: " << std::dec << m_mru[m_mru_idx].valid_len << "]\n"; 114 logMsg(oss.str()); 115 #endif 116 INC_PAGES(); 117 118 // increment the next new page counter. 119 m_mru_next_new++; 120 if (m_mru_next_new == MEM_ACC_CACHE_MRU_SIZE) 121 m_mru_next_new = 0; 122 123 if (blockInPage(address, reqBytes)) /* check we got the data we needed */ 124 { 125 bytesRead = reqBytes; 126 memcpy(byteBuffer, &m_mru[m_mru_idx].data[address - m_mru[m_mru_idx].st_addr], reqBytes); 127 INC_RL(m_mru_idx); 128 } 129 else 130 { 131 #ifdef LOG_CACHE_OPS 132 oss.str(""); 133 oss << "TrcMemAccCache:: miss-after-load [page: " << std::dec << m_mru_idx << "[addr:0x" << std::hex << address << ", bytes: " << std::dec << m_mru[m_mru_idx].valid_len << "]\n"; 134 logMsg(oss.str()); 135 #endif 136 INC_MISS(); 137 } 138 } 139 } 140 } 141 *numBytes = bytesRead; 142 return err; 143 } 144 logMsg(const std::string & szMsg)145 void TrcMemAccCache::logMsg(const std::string &szMsg) 146 { 147 if (m_err_log) 148 m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO, OCSD_ERR_SEV_INFO, szMsg); 149 } 150 setErrorLog(ITraceErrorLog * log)151 void TrcMemAccCache::setErrorLog(ITraceErrorLog *log) 152 { 153 m_err_log = log; 154 } 155 logAndClearCounts()156 void TrcMemAccCache::logAndClearCounts() 157 { 158 #ifdef LOG_CACHE_STATS 159 std::ostringstream oss; 160 161 oss << "TrcMemAccCache:: cache performance: hits(" << std::dec << m_hits << "), miss(" << m_misses << "), pages(" << m_pages << ")\n"; 162 logMsg(oss.str()); 163 for (int i = 0; i < MEM_ACC_CACHE_MRU_SIZE; i++) 164 { 165 if (m_hit_rl_max[i] < m_hit_rl[i]) 166 m_hit_rl_max[i] = m_hit_rl[i]; 167 oss.str(""); 168 oss << "Run length max page " << std::dec << i << ": " << m_hit_rl_max[i] << "\n"; 169 logMsg(oss.str()); 170 } 171 m_hits = m_misses = m_pages = 0; 172 #endif 173 } 174 175 176 /* End of File trc_mem_acc_cache.cpp */ 177