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