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