aboutsummaryrefslogtreecommitdiff
path: root/decoder/source/mem_acc
diff options
context:
space:
mode:
Diffstat (limited to 'decoder/source/mem_acc')
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_bufptr.cpp2
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_cache.cpp176
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_cb.cpp4
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_file.cpp2
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_mapper.cpp75
5 files changed, 249 insertions, 10 deletions
diff --git a/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp b/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp
index fee663b30d06..25c736387c0b 100644
--- a/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp
+++ b/decoder/source/mem_acc/trc_mem_acc_bufptr.cpp
@@ -42,7 +42,7 @@ TrcMemAccBufPtr::TrcMemAccBufPtr(const ocsd_vaddr_t s_address, const uint8_t *p_
{
}
-const uint32_t TrcMemAccBufPtr::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint32_t reqBytes, uint8_t *byteBuffer)
+const uint32_t TrcMemAccBufPtr::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t trcID, const uint32_t reqBytes, uint8_t *byteBuffer)
{
// mapper wlll filter memory spaces.
uint32_t bytesRead = bytesInRange(address,reqBytes); // check bytes available
diff --git a/decoder/source/mem_acc/trc_mem_acc_cache.cpp b/decoder/source/mem_acc/trc_mem_acc_cache.cpp
new file mode 100644
index 000000000000..444314ee9da6
--- /dev/null
+++ b/decoder/source/mem_acc/trc_mem_acc_cache.cpp
@@ -0,0 +1,176 @@
+/*!
+* \file trc_mem_acc_cache.cpp
+* \brief OpenCSD : Memory accessor cache.
+*
+* \copyright Copyright (c) 2018, ARM Limited. All Rights Reserved.
+*/
+
+/*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* 3. Neither the name of the copyright holder nor the names of its contributors
+* may be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+#include <sstream>
+#include <iomanip>
+#include "mem_acc/trc_mem_acc_cache.h"
+#include "mem_acc/trc_mem_acc_base.h"
+#include "interfaces/trc_error_log_i.h"
+
+#ifdef LOG_CACHE_STATS
+#define INC_HITS_RL(idx) m_hits++; m_hit_rl[m_mru_idx]++;
+#define INC_MISS() m_misses++;
+#define INC_PAGES() m_pages++;
+#define SET_MAX_RL(idx) \
+ { \
+ if (m_hit_rl_max[idx] < m_hit_rl[idx]) \
+ m_hit_rl_max[idx] = m_hit_rl[idx]; \
+ m_hit_rl[idx] = 0; \
+ }
+#define INC_RL(idx) m_hit_rl[m_mru_idx]++;
+#else
+#define INC_HITS_RL(idx)
+#define INC_MISS()
+#define INC_PAGES()
+#define SET_MAX_RL(idx)
+#define INC_RL(idx)
+#endif
+
+// uncomment to log cache ops
+//#define LOG_CACHE_OPS
+
+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)
+{
+ uint32_t bytesRead = 0, reqBytes = *numBytes;
+ ocsd_err_t err = OCSD_OK;
+
+#ifdef LOG_CACHE_OPS
+ std::ostringstream oss;
+#endif
+
+ if (m_bCacheEnabled)
+ {
+ if (blockInCache(address, reqBytes))
+ {
+ bytesRead = reqBytes;
+ memcpy(byteBuffer, &m_mru[m_mru_idx].data[address - m_mru[m_mru_idx].st_addr], reqBytes);
+#ifdef LOG_CACHE_OPS
+ oss << "TrcMemAccCache:: hit [page: " << std::dec << m_mru_idx << "[addr:0x" << std::hex << address << ", bytes: " << std::dec << reqBytes << "]\n";
+ logMsg(oss.str());
+#endif
+ INC_HITS_RL(m_mru_idx);
+ }
+ else
+ {
+ INC_MISS();
+#ifdef LOG_CACHE_OPS
+ oss << "TrcMemAccCache:: miss [addr:0x" << std::hex << address << ", bytes: " << std::dec << reqBytes << "]\n";
+ logMsg(oss.str());
+#endif
+ /* need a new cache page - check the underlying accessor for the data */
+ m_mru_idx = m_mru_next_new;
+ 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]);
+
+ /* check return length valid - v bad if return length more than request */
+ if (m_mru[m_mru_idx].valid_len > MEM_ACC_CACHE_PAGE_SIZE)
+ {
+ m_mru[m_mru_idx].valid_len = 0; // set to nothing returned.
+ err = OCSD_ERR_MEM_ACC_BAD_LEN;
+ }
+
+ if (m_mru[m_mru_idx].valid_len > 0)
+ {
+ // got some data - so save the
+ m_mru[m_mru_idx].st_addr = address;
+
+ // log the run length hit counts
+ SET_MAX_RL(m_mru_idx);
+
+#ifdef LOG_CACHE_OPS
+ oss.str("");
+ 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";
+ logMsg(oss.str());
+#endif
+ INC_PAGES();
+
+ // increment the next new page counter.
+ m_mru_next_new++;
+ if (m_mru_next_new == MEM_ACC_CACHE_MRU_SIZE)
+ m_mru_next_new = 0;
+
+ if (blockInPage(address, reqBytes)) /* check we got the data we needed */
+ {
+ bytesRead = reqBytes;
+ memcpy(byteBuffer, &m_mru[m_mru_idx].data[address - m_mru[m_mru_idx].st_addr], reqBytes);
+ INC_RL(m_mru_idx);
+ }
+ else
+ {
+#ifdef LOG_CACHE_OPS
+ oss.str("");
+ 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";
+ logMsg(oss.str());
+#endif
+ INC_MISS();
+ }
+ }
+ }
+ }
+ *numBytes = bytesRead;
+ return err;
+}
+
+void TrcMemAccCache::logMsg(const std::string &szMsg)
+{
+ if (m_err_log)
+ m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO, OCSD_ERR_SEV_INFO, szMsg);
+}
+
+void TrcMemAccCache::setErrorLog(ITraceErrorLog *log)
+{
+ m_err_log = log;
+}
+
+void TrcMemAccCache::logAndClearCounts()
+{
+#ifdef LOG_CACHE_STATS
+ std::ostringstream oss;
+
+ oss << "TrcMemAccCache:: cache performance: hits(" << std::dec << m_hits << "), miss(" << m_misses << "), pages(" << m_pages << ")\n";
+ logMsg(oss.str());
+ for (int i = 0; i < MEM_ACC_CACHE_MRU_SIZE; i++)
+ {
+ if (m_hit_rl_max[i] < m_hit_rl[i])
+ m_hit_rl_max[i] = m_hit_rl[i];
+ oss.str("");
+ oss << "Run length max page " << std::dec << i << ": " << m_hit_rl_max[i] << "\n";
+ logMsg(oss.str());
+ }
+ m_hits = m_misses = m_pages = 0;
+#endif
+}
+
+
+/* End of File trc_mem_acc_cache.cpp */
diff --git a/decoder/source/mem_acc/trc_mem_acc_cb.cpp b/decoder/source/mem_acc/trc_mem_acc_cb.cpp
index 28dedcb0fba6..1a1565bff038 100644
--- a/decoder/source/mem_acc/trc_mem_acc_cb.cpp
+++ b/decoder/source/mem_acc/trc_mem_acc_cb.cpp
@@ -19,13 +19,15 @@ TrcMemAccCB::TrcMemAccCB(const ocsd_vaddr_t s_address,
}
/** Memory access override - allow decoder to read bytes from the buffer. */
-const uint32_t TrcMemAccCB::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t memSpace, const uint32_t reqBytes, uint8_t *byteBuffer)
+const uint32_t TrcMemAccCB::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t memSpace, const uint8_t trcID, const uint32_t reqBytes, uint8_t *byteBuffer)
{
// if we have a callback object, use it to call back.
if(m_p_CBclass)
return m_p_CBclass->readBytes(address,memSpace,reqBytes,byteBuffer);
if(m_p_CBfn)
return m_p_CBfn(m_p_cbfn_context, address,memSpace,reqBytes,byteBuffer);
+ if (m_p_CBIDfn)
+ return m_p_CBIDfn(m_p_cbfn_context, address, memSpace, trcID, reqBytes, byteBuffer);
return 0;
}
diff --git a/decoder/source/mem_acc/trc_mem_acc_file.cpp b/decoder/source/mem_acc/trc_mem_acc_file.cpp
index 87901c83dcee..25b718ea589c 100644
--- a/decoder/source/mem_acc/trc_mem_acc_file.cpp
+++ b/decoder/source/mem_acc/trc_mem_acc_file.cpp
@@ -199,7 +199,7 @@ TrcMemAccessorFile * TrcMemAccessorFile::getExistingFileAccessor(const std::stri
/***************************************************/
/* accessor instance functions */
/***************************************************/
-const uint32_t TrcMemAccessorFile::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint32_t reqBytes, uint8_t *byteBuffer)
+const uint32_t TrcMemAccessorFile::readBytes(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t trcID, const uint32_t reqBytes, uint8_t *byteBuffer)
{
if(!m_mem_file.is_open())
return 0;
diff --git a/decoder/source/mem_acc/trc_mem_acc_mapper.cpp b/decoder/source/mem_acc/trc_mem_acc_mapper.cpp
index 6d4f085c6fa0..53edfe1a1616 100644
--- a/decoder/source/mem_acc/trc_mem_acc_mapper.cpp
+++ b/decoder/source/mem_acc/trc_mem_acc_mapper.cpp
@@ -34,17 +34,23 @@
#include "mem_acc/trc_mem_acc_mapper.h"
#include "mem_acc/trc_mem_acc_file.h"
+#include "common/ocsd_error.h"
/************************************************************************************/
/* mappers base class */
/************************************************************************************/
+#define USING_MEM_ACC_CACHE
+
TrcMemAccMapper::TrcMemAccMapper() :
m_acc_curr(0),
m_trace_id_curr(0),
m_using_trace_id(false),
m_err_log(0)
{
+#ifdef USING_MEM_ACC_CACHE
+ m_cache.enableCaching(true);
+#endif
}
TrcMemAccMapper::TrcMemAccMapper(bool using_trace_id) :
@@ -53,27 +59,64 @@ TrcMemAccMapper::TrcMemAccMapper(bool using_trace_id) :
m_using_trace_id(using_trace_id),
m_err_log(0)
{
+#ifdef USING_MEM_ACC_CACHE
+ m_cache.enableCaching(true);
+#endif
}
TrcMemAccMapper::~TrcMemAccMapper()
{
}
+void TrcMemAccMapper::setErrorLog(ITraceErrorLog *err_log_i)
+{
+ m_err_log = err_log_i;
+ m_cache.setErrorLog(err_log_i);
+}
+
// memory access interface
ocsd_err_t TrcMemAccMapper::ReadTargetMemory(const ocsd_vaddr_t address, const uint8_t cs_trace_id, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer)
{
bool bReadFromCurr = true;
+ uint32_t readBytes = 0;
+ ocsd_err_t err = OCSD_OK;
/* see if the address is in any range we know */
- if(!readFromCurrent(address, mem_space, cs_trace_id))
- bReadFromCurr = findAccessor(address, mem_space, cs_trace_id);
+ if (!readFromCurrent(address, mem_space, cs_trace_id))
+ {
+ bReadFromCurr = findAccessor(address, mem_space, cs_trace_id);
+
+ // found a new accessor - invalidate any cache entries used by the previous one.
+ if (m_cache.enabled() && bReadFromCurr)
+ m_cache.invalidateAll();
+ }
/* if bReadFromCurr then we know m_acc_curr is set */
- if(bReadFromCurr)
- *num_bytes = m_acc_curr->readBytes(address, mem_space, *num_bytes,p_buffer);
- else
- *num_bytes = 0;
- return OCSD_OK;
+ if (bReadFromCurr)
+ {
+ // use cache if enabled and the amount fits into a cache page
+ if (m_cache.enabled_for_size(*num_bytes))
+ {
+ // read from cache - or load a new cache page and read....
+ readBytes = *num_bytes;
+ err = m_cache.readBytesFromCache(m_acc_curr, address, mem_space, cs_trace_id, &readBytes, p_buffer);
+ if (err != OCSD_OK)
+ LogWarn(err, "Mem Acc: Cache access error");
+ }
+ else
+ {
+ readBytes = m_acc_curr->readBytes(address, mem_space, cs_trace_id, *num_bytes, p_buffer);
+ // guard against bad accessor returns (e.g. callback not obeying the rules for return values)
+ if (readBytes > *num_bytes)
+ {
+ err = OCSD_ERR_MEM_ACC_BAD_LEN;
+ LogWarn(err,"Mem acc: bad return length");
+ }
+ }
+ }
+
+ *num_bytes = readBytes;
+ return err;
}
void TrcMemAccMapper::RemoveAllAccessors()
@@ -84,8 +127,12 @@ void TrcMemAccMapper::RemoveAllAccessors()
{
TrcMemAccFactory::DestroyAccessor(pAcc);
pAcc = getNextAccessor();
+ if (m_cache.enabled())
+ m_cache.invalidateAll();
}
clearAccessorList();
+ if (m_cache.enabled())
+ m_cache.logAndClearCounts();
}
ocsd_err_t TrcMemAccMapper::RemoveAccessorByAddress(const ocsd_vaddr_t st_address, const ocsd_mem_space_acc_t mem_space, const uint8_t cs_trace_id /* = 0 */)
@@ -95,9 +142,13 @@ ocsd_err_t TrcMemAccMapper::RemoveAccessorByAddress(const ocsd_vaddr_t st_addres
{
err = RemoveAccessor(m_acc_curr);
m_acc_curr = 0;
+ if (m_cache.enabled())
+ m_cache.invalidateAll();
}
else
err = OCSD_ERR_INVALID_PARAM_VAL;
+ if (m_cache.enabled())
+ m_cache.logAndClearCounts();
return err;
}
@@ -107,6 +158,16 @@ void TrcMemAccMapper::LogMessage(const std::string &msg)
m_err_log->LogMessage(ITraceErrorLog::HANDLE_GEN_INFO,OCSD_ERR_SEV_INFO,msg);
}
+void TrcMemAccMapper::LogWarn(const ocsd_err_t err, const std::string &msg)
+{
+ if (m_err_log)
+ {
+ ocsdError err_ocsd(OCSD_ERR_SEV_WARN,err,msg);
+ m_err_log->LogError(ITraceErrorLog::HANDLE_GEN_INFO, &err_ocsd);
+ }
+}
+
+
/************************************************************************************/
/* mappers global address space class - no differentiation in core trace IDs */
/************************************************************************************/