]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/opencsd/decoder/source/mem_acc/trc_mem_acc_cache.cpp
Re-add opencsd as a vendor import from the dist directory
[FreeBSD/FreeBSD.git] / contrib / opencsd / decoder / source / mem_acc / trc_mem_acc_cache.cpp
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
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
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
151 void TrcMemAccCache::setErrorLog(ITraceErrorLog *log)
152 {
153     m_err_log = log;
154 }
155
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 */