aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Leach <mike.leach@linaro.org>2023-11-06 20:58:04 +0000
committerMike Leach <mike.leach@linaro.org>2023-12-18 14:57:54 +0000
commit8f3a7b29f2faff905380ad5e9a77bd5d82f86773 (patch)
tree7496cfafdc87990fed910ee949eec0edae783a49
parent12eb668a24fb36233db62c4fd114504193635abe (diff)
downloadOpenCSD-8f3a7b29f2faff905380ad5e9a77bd5d82f86773.tar.gz
opencsd: memacc: update caching for accessors to allow runtime flexibility
Caching of memory data is now tunable either from the client by API, or via runtime environment variables. Signed-off-by: Mike Leach <mike.leach@linaro.org>
-rw-r--r--decoder/include/mem_acc/trc_mem_acc_base.h6
-rw-r--r--decoder/include/mem_acc/trc_mem_acc_cache.h138
-rw-r--r--decoder/include/mem_acc/trc_mem_acc_mapper.h6
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_base.cpp42
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_cache.cpp270
-rw-r--r--decoder/source/mem_acc/trc_mem_acc_mapper.cpp30
6 files changed, 402 insertions, 90 deletions
diff --git a/decoder/include/mem_acc/trc_mem_acc_base.h b/decoder/include/mem_acc/trc_mem_acc_base.h
index 7f17bde..29196be 100644
--- a/decoder/include/mem_acc/trc_mem_acc_base.h
+++ b/decoder/include/mem_acc/trc_mem_acc_base.h
@@ -110,7 +110,7 @@ public:
virtual const uint32_t bytesInRange(const ocsd_vaddr_t s_address, const uint32_t reqBytes) const;
/*!
- * test is supplied range accessor overlaps this range.
+ * test if supplied range accessor overlaps this range.
*
* @param *p_test_acc : Accessor to test for overlap.
*
@@ -149,11 +149,13 @@ public:
/* memory access info logging */
virtual void getMemAccString(std::string &accStr) const;
+ static void getMemAccSpaceString(std::string& spaceStr, const ocsd_mem_space_acc_t mem_space);
+
protected:
ocsd_vaddr_t m_startAddress; /**< accessible range start address */
ocsd_vaddr_t m_endAddress; /**< accessible range end address */
const MemAccTypes m_type; /**< memory accessor type */
- ocsd_mem_space_acc_t m_mem_space;
+ ocsd_mem_space_acc_t m_mem_space; /**< Matching memory space of this acessor */
};
inline TrcMemAccessorBase::TrcMemAccessorBase(MemAccTypes accType, ocsd_vaddr_t startAddr, ocsd_vaddr_t endAddr) :
diff --git a/decoder/include/mem_acc/trc_mem_acc_cache.h b/decoder/include/mem_acc/trc_mem_acc_cache.h
index 5e81c2a..351d424 100644
--- a/decoder/include/mem_acc/trc_mem_acc_cache.h
+++ b/decoder/include/mem_acc/trc_mem_acc_cache.h
@@ -38,8 +38,17 @@
#include <string>
#include "opencsd/ocsd_if_types.h"
-#define MEM_ACC_CACHE_PAGE_SIZE 256
-#define MEM_ACC_CACHE_MRU_SIZE 12
+#define MEM_ACC_CACHE_DEFAULT_PAGE_SIZE 2048
+#define MEM_ACC_CACHE_DEFAULT_MRU_SIZE 16
+#define MEM_ACC_CACHE_PAGE_SIZE_MAX 16384
+#define MEM_ACC_CACHE_MRU_SIZE_MAX 256
+#define MEM_ACC_CACHE_PAGE_SIZE_MIN 64
+#define MEM_ACC_CACHE_MRU_SIZE_MIN 4
+
+#define OCSD_ENV_MEMACC_CACHE_OFF "OPENCSD_MEMACC_CACHE_OFF"
+#define OCSD_ENV_MEMACC_CACHE_PG_SIZE "OPENCSD_MEMACC_CACHE_PAGE_SIZE"
+#define OCSD_ENV_MEMACC_CACHE_PG_NUM "OPENCSD_MEMACC_CACHE_PAGE_NUM"
+
class TrcMemAccessorBase;
class ITraceErrorLog;
@@ -47,101 +56,142 @@ class ITraceErrorLog;
typedef struct cache_block {
ocsd_vaddr_t st_addr;
uint32_t valid_len;
- uint8_t data[MEM_ACC_CACHE_PAGE_SIZE];
+ uint8_t* data;
+ uint8_t trcID; // trace ID associated with the page
+ uint32_t use_sequence; // number representing the sequence of allocation to evict oldest page.
} cache_block_t;
// enable define to collect stats for debugging / cache performance tests
-//#define LOG_CACHE_STATS
-
-
-/** class TrcMemAccCache - cache small amounts of data from accessors to speed up decode. */
+// #define LOG_CACHE_STATS
+
+
+/** class TrcMemAccCache - cache small amounts of data from accessors to speed up decode.
+ *
+ * Reduce the need to read files / make callbacks into clients when walking memory images.
+ *
+ * Caching is done on a per Core/Trace ID basis - all caches from that ID are invalidated when a context
+ * switch appears on the core. This means that we do not account for memory spaces in the cache pages as
+ * these only change via a context switch.
+ *
+ * Memory space is used on cache miss if reading data from the underlying accessor (file / callback).
+ */
class TrcMemAccCache
{
public:
TrcMemAccCache();
- ~TrcMemAccCache() {};
+ ~TrcMemAccCache();
+
+ /* cache enabling and usage */
+ ocsd_err_t enableCaching(bool bEnable);
+ ocsd_err_t setCacheSizes(const uint16_t page_size, const int nr_pages);
- void enableCaching(bool bEnable) { m_bCacheEnabled = bEnable; };
- void invalidateAll();
const bool enabled() const { return m_bCacheEnabled; };
const bool enabled_for_size(const uint32_t reqSize) const
{
- return (m_bCacheEnabled && (reqSize <= MEM_ACC_CACHE_PAGE_SIZE));
+ return (m_bCacheEnabled && (reqSize <= m_mru_page_size));
}
-
-
- /** read bytes from cache if possible - load new page if needed, bail out if data not available */
+
+ /* cache invalidation */
+ void invalidateAll();
+ void invalidateByTraceID(int8_t trcID);
+ void clearPage(cache_block_t* page);
+
+ /** read bytes from cache if possible - load new page if needed from underlying accessor, bail out if data not available */
ocsd_err_t 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);
void setErrorLog(ITraceErrorLog *log);
void logAndClearCounts();
+ /* look for runtime cache tuning vars */
+ static void getenvMemaccCacheSizes(bool& enable, int& page_size, int& num_pages);
+
private:
- bool blockInCache(const ocsd_vaddr_t address, const uint32_t reqBytes); // run through each page to look for data.
- bool blockInPage(const ocsd_vaddr_t address, const uint32_t reqBytes);
+ bool blockInCache(const ocsd_vaddr_t address, const uint32_t reqBytes, const uint8_t trcID); // run through each page to look for data.
+ bool blockInPage(const ocsd_vaddr_t address, const uint32_t reqBytes, const uint8_t trcID);
+
void logMsg(const std::string &szMsg);
+ int findNewPage();
+ void incSequence(); // increment sequence on current block
+
+ ocsd_err_t createCaches(); // create caches according to current sizes
+ void destroyCaches(); // destroy the cache blocks
+
+ cache_block_t *m_mru; // cache pages
+ int m_mru_idx = 0; // in use index - most recently used page
+ uint16_t m_mru_page_size; // page size
+ int m_mru_num_pages; // number of pages
+ uint32_t m_mru_sequence; // allocation & use sequence number
- cache_block_t m_mru[MEM_ACC_CACHE_MRU_SIZE];
- int m_mru_idx = 0; // in use index
- int m_mru_next_new = 0; // next new page at this index.
bool m_bCacheEnabled = false;
#ifdef LOG_CACHE_STATS
uint32_t m_hits = 0;
uint32_t m_misses = 0;
uint32_t m_pages = 0;
- uint32_t m_hit_rl[MEM_ACC_CACHE_MRU_SIZE];
- uint32_t m_hit_rl_max[MEM_ACC_CACHE_MRU_SIZE];
+ uint32_t* m_hit_rl = 0;
+ uint32_t* m_hit_rl_max = 0;
#endif
ITraceErrorLog *m_err_log = 0;
};
-inline TrcMemAccCache::TrcMemAccCache()
+inline TrcMemAccCache::TrcMemAccCache() :
+ m_mru(0), m_mru_sequence(1)
{
- for (int i = 0; i < MEM_ACC_CACHE_MRU_SIZE; i++)
- {
- m_mru[i].st_addr = 0;
- m_mru[i].valid_len = 0;
-#ifdef LOG_CACHE_STATS
- m_hit_rl[i] = 0;
- m_hit_rl_max[i] = 0;
-#endif
- }
+ /* set default cache sizes */
+ m_mru_page_size = MEM_ACC_CACHE_DEFAULT_PAGE_SIZE;
+ m_mru_num_pages = MEM_ACC_CACHE_DEFAULT_MRU_SIZE;
}
-inline bool TrcMemAccCache::blockInPage(const ocsd_vaddr_t address, const uint32_t reqBytes)
+inline TrcMemAccCache::~TrcMemAccCache()
+{
+ destroyCaches();
+}
+
+
+inline bool TrcMemAccCache::blockInPage(const ocsd_vaddr_t address, const uint32_t reqBytes, const uint8_t trcID)
{
+ /* check has data, trcID and mem space */
+ if ((m_mru[m_mru_idx].trcID != trcID) ||
+ (m_mru[m_mru_idx].valid_len == 0)
+ )
+ return false;
+
+ /* check block is in this page */
if ((m_mru[m_mru_idx].st_addr <= address) &&
m_mru[m_mru_idx].st_addr + m_mru[m_mru_idx].valid_len >= (address + reqBytes))
return true;
return false;
}
-inline bool TrcMemAccCache::blockInCache(const ocsd_vaddr_t address, const uint32_t reqBytes)
+inline bool TrcMemAccCache::blockInCache(const ocsd_vaddr_t address, const uint32_t reqBytes, const uint8_t trcID)
{
- int tests = MEM_ACC_CACHE_MRU_SIZE;
+ int tests = m_mru_num_pages;
while (tests)
{
- if (blockInPage(address, reqBytes))
+ if (blockInPage(address, reqBytes, trcID))
return true; // found address in page
+#ifdef LOG_CACHE_STATS
+ // miss counts of current page only - to determine if we hit other page
+ if (tests == m_mru_num_pages)
+ m_misses++;
+#endif
+
tests--;
m_mru_idx++;
- if (m_mru_idx == MEM_ACC_CACHE_MRU_SIZE)
+ if (m_mru_idx == m_mru_num_pages)
m_mru_idx = 0;
}
return false;
}
-inline void TrcMemAccCache::invalidateAll()
+// zero out page parameters rendering it empty
+inline void TrcMemAccCache::clearPage(cache_block_t* page)
{
- for (int i = 0; i < MEM_ACC_CACHE_MRU_SIZE; i++)
- {
- m_mru[i].valid_len = 0;
- m_mru[i].st_addr = 0;
- }
- m_mru_idx = 0;
- m_mru_next_new = 0;
+ page->use_sequence = 0;
+ page->st_addr = 0;
+ page->valid_len = 0;
+ page->trcID = OCSD_BAD_CS_SRC_ID;
}
#endif // ARM_TRC_MEM_ACC_CACHE_H_INCLUDED
diff --git a/decoder/include/mem_acc/trc_mem_acc_mapper.h b/decoder/include/mem_acc/trc_mem_acc_mapper.h
index f4523c7..4d906f2 100644
--- a/decoder/include/mem_acc/trc_mem_acc_mapper.h
+++ b/decoder/include/mem_acc/trc_mem_acc_mapper.h
@@ -84,6 +84,12 @@ public:
// print out the ranges in this mapper.
virtual void logMappedRanges() = 0;
+ // control memory access caching at runtime
+ ocsd_err_t enableCaching(bool bEnable);
+
+ // set cache page size and number of pages (max 16k size, 256 pages)
+ ocsd_err_t setCacheSizes(uint16_t page_size, int num_pages);
+
protected:
virtual bool findAccessor(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t cs_trace_id) = 0; // set m_acc_curr if found valid range, leave unchanged if not.
virtual bool readFromCurrent(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t cs_trace_id) = 0;
diff --git a/decoder/source/mem_acc/trc_mem_acc_base.cpp b/decoder/source/mem_acc/trc_mem_acc_base.cpp
index 1250bdc..be45b66 100644
--- a/decoder/source/mem_acc/trc_mem_acc_base.cpp
+++ b/decoder/source/mem_acc/trc_mem_acc_base.cpp
@@ -94,16 +94,17 @@ void TrcMemAccFactory::DestroyAccessor(TrcMemAccessorBase *pAccessor)
/* memory access info logging */
-void TrcMemAccessorBase::getMemAccString(std::string &accStr) const
+void TrcMemAccessorBase::getMemAccString(std::string& accStr) const
{
std::ostringstream oss;
+ std::string spaceStr;
- switch(m_type)
+ switch (m_type)
{
case MEMACC_FILE:
oss << "FileAcc; Range::0x";
break;
-
+
case MEMACC_BUFPTR:
oss << "BuffAcc; Range::0x";
break;
@@ -112,37 +113,60 @@ void TrcMemAccessorBase::getMemAccString(std::string &accStr) const
oss << "CB Acc; Range::0x";
break;
- default:
+ default:
oss << "UnknAcc; Range::0x";
break;
}
oss << std::hex << std::setw(2) << std::setfill('0') << m_startAddress << ":" << m_endAddress;
oss << "; Mem Space::";
- switch(m_mem_space)
+ getMemAccSpaceString(spaceStr, m_mem_space);
+ oss << spaceStr;
+
+ accStr = oss.str();
+}
+
+void TrcMemAccessorBase::getMemAccSpaceString(std::string &spaceStr, const ocsd_mem_space_acc_t mem_space)
+{
+ std::ostringstream oss;
+
+ switch(mem_space)
{
case OCSD_MEM_SPACE_EL1S: oss << "EL1S"; break;
case OCSD_MEM_SPACE_EL1N: oss << "EL1N"; break;
- case OCSD_MEM_SPACE_EL2: oss << "EL2"; break;
+ case OCSD_MEM_SPACE_EL2: oss << "EL2N"; break;
case OCSD_MEM_SPACE_EL3: oss << "EL3"; break;
+ case OCSD_MEM_SPACE_EL2S: oss << "EL2S"; break;
+ case OCSD_MEM_SPACE_EL1R: oss << "EL1R"; break;
+ case OCSD_MEM_SPACE_EL2R: oss << "EL2R"; break;
+ case OCSD_MEM_SPACE_ROOT: oss << "Root"; break;
case OCSD_MEM_SPACE_S: oss << "Any S"; break;
case OCSD_MEM_SPACE_N: oss << "Any NS"; break;
+ case OCSD_MEM_SPACE_R: oss << "Any R"; break;
case OCSD_MEM_SPACE_ANY: oss << "Any"; break;
default:
{
- uint8_t MSBits = (uint8_t)m_mem_space;
+ uint8_t MSBits = (uint8_t)mem_space;
if(MSBits & (uint8_t)OCSD_MEM_SPACE_EL1S)
oss << "EL1S,";
if(MSBits & (uint8_t)OCSD_MEM_SPACE_EL1N)
oss << "EL1N,";
if(MSBits & (uint8_t)OCSD_MEM_SPACE_EL2)
- oss << "EL2,";
+ oss << "EL2N,";
if(MSBits & (uint8_t)OCSD_MEM_SPACE_EL3)
oss << "EL3,";
+ if (MSBits & (uint8_t)OCSD_MEM_SPACE_EL2S)
+ oss << "EL2S,";
+ if (MSBits & (uint8_t)OCSD_MEM_SPACE_EL1R)
+ oss << "EL1R,";
+ if (MSBits & (uint8_t)OCSD_MEM_SPACE_EL2R)
+ oss << "EL2R,";
+ if (MSBits & (uint8_t)OCSD_MEM_SPACE_ROOT)
+ oss << "Root,";
}
break;
}
- accStr = oss.str();
+ spaceStr = oss.str();
}
/* End of File trc_mem_acc_base.cpp */
diff --git a/decoder/source/mem_acc/trc_mem_acc_cache.cpp b/decoder/source/mem_acc/trc_mem_acc_cache.cpp
index 444314e..903ab73 100644
--- a/decoder/source/mem_acc/trc_mem_acc_cache.cpp
+++ b/decoder/source/mem_acc/trc_mem_acc_cache.cpp
@@ -59,42 +59,237 @@
#endif
// uncomment to log cache ops
-//#define LOG_CACHE_OPS
+// #define LOG_CACHE_OPS
+
+ocsd_err_t TrcMemAccCache::createCaches()
+{
+ if (m_mru)
+ destroyCaches();
+ m_mru = (cache_block_t*) new (std::nothrow) cache_block_t[m_mru_num_pages];
+ if (!m_mru)
+ return OCSD_ERR_MEM;
+ for (int i = 0; i < m_mru_num_pages; i++) {
+ m_mru[i].data = new (std::nothrow) uint8_t[m_mru_page_size];
+ if (!m_mru[i].data)
+ return OCSD_ERR_MEM;
+ clearPage(&m_mru[i]);
+ }
+#ifdef LOG_CACHE_STATS
+ m_hit_rl = (uint32_t *) new (std::nothrow) uint32_t[m_mru_num_pages];
+ m_hit_rl_max = (uint32_t*) new (std::nothrow) uint32_t[m_mru_num_pages];
+ if (!m_hit_rl || !m_hit_rl_max)
+ return OCSD_ERR_MEM;
+ for (int j = 0; j < m_mru_num_pages; j++) {
+ m_hit_rl[j] = 0;
+ m_hit_rl_max[j] = 0;
+ }
+#endif
+
+ return OCSD_OK;
+}
+
+void TrcMemAccCache::destroyCaches()
+{
+ if (m_mru) {
+ for (int i = 0; i < m_mru_num_pages; i++)
+ delete[] m_mru[i].data;
+ delete[] m_mru;
+ m_mru = 0;
+ }
+#ifdef LOG_CACHE_STATS
+ if (m_hit_rl)
+ delete[] m_hit_rl;
+ if (m_hit_rl_max)
+ delete[] m_hit_rl_max;
+ m_hit_rl = 0;
+ m_hit_rl_max = 0;
+#endif
+
+}
+
+void TrcMemAccCache::getenvMemaccCacheSizes(bool& enable, int& page_size, int& num_pages)
+{
+ char* env_var;
+ long env_val;
+
+ /* set defaults */
+ enable = true;
+ page_size = MEM_ACC_CACHE_DEFAULT_PAGE_SIZE;
+ num_pages = MEM_ACC_CACHE_DEFAULT_MRU_SIZE;
+
+ /* check environment for adjustments */
+
+ /* override the default on switch? if so no need to look further */
+ if ((env_var = getenv(OCSD_ENV_MEMACC_CACHE_OFF)) != NULL)
+ {
+ enable = false;
+ return;
+ }
+
+ /* check for tweak in page size */
+ if ((env_var = getenv(OCSD_ENV_MEMACC_CACHE_PG_SIZE)) != NULL)
+ {
+ env_val = strtol(env_var, NULL, 0);
+ /*
+ * if no valid conversion then env_val = 0,
+ * otherwise set val and allow TrcMemAccCache::setCacheSizes
+ * fn to ensure the value in bounds
+ */
+ if (env_val > 0)
+ page_size = (int)env_val;
+ }
+
+ /* check for tweak in number of pages */
+ if ((env_var = getenv(OCSD_ENV_MEMACC_CACHE_PG_NUM)) != NULL)
+ {
+ env_val = strtol(env_var, NULL, 0);
+ /*
+ * if no valid conversion then env_val = 0,
+ * otherwise set val and allow TrcMemAccCache::setCacheSizes
+ * fn to ensure the value in bounds
+ */
+ if (env_val > 0)
+ num_pages = (int)env_val;
+ }
+
+}
+
+ocsd_err_t TrcMemAccCache::enableCaching(bool bEnable)
+{
+ ocsd_err_t err = OCSD_OK;
+
+ if (bEnable)
+ err = createCaches();
+ else
+ destroyCaches();
+ m_bCacheEnabled = bEnable;
+
+ return err;
+}
+
+ocsd_err_t TrcMemAccCache::setCacheSizes(const uint16_t page_size, const int nr_pages)
+{
+ /* remove any caches with the existing sizes */
+ destroyCaches();
+
+ /* set page size within Max/Min range */
+ if (page_size > MEM_ACC_CACHE_PAGE_SIZE_MAX)
+ m_mru_page_size = MEM_ACC_CACHE_PAGE_SIZE_MAX;
+ else if (page_size < MEM_ACC_CACHE_PAGE_SIZE_MIN)
+ m_mru_page_size = MEM_ACC_CACHE_PAGE_SIZE_MIN;
+ else
+ m_mru_page_size = page_size;
+
+ /* set num pages within max/min range */
+ if (nr_pages > MEM_ACC_CACHE_MRU_SIZE_MAX)
+ m_mru_num_pages = MEM_ACC_CACHE_MRU_SIZE_MAX;
+ else if (nr_pages < MEM_ACC_CACHE_MRU_SIZE_MIN)
+ m_mru_num_pages = MEM_ACC_CACHE_MRU_SIZE_MIN;
+ else
+ m_mru_num_pages = nr_pages;
+
+ /* re-create with new sizes */
+ return createCaches();
+}
+
+/* return index of unused page, or oldest used page by sequence number */
+int TrcMemAccCache::findNewPage()
+{
+ uint32_t oldest_seq;
+ int current_idx, oldest_idx;
+#ifdef LOG_CACHE_OPS
+ std::ostringstream oss;
+#endif
+
+ /* set up search indexes and check the current search index has not wrapped. */
+ current_idx = m_mru_idx + 1;
+ oldest_idx = m_mru_idx;
+ oldest_seq = 0;
+ if (current_idx >= m_mru_num_pages)
+ current_idx = 0;
+
+ /* search forwards from m_mru_idx + 1 until we wrap and hit the index again */
+ while (current_idx != m_mru_idx) {
+ if (m_mru[current_idx].use_sequence == 0) {
+#ifdef LOG_CACHE_OPS
+ oss << "TrcMemAccCache:: ALI-allocate clean page: [page: " << std::dec << current_idx << "]\n";
+ logMsg(oss.str());
+#endif
+ return current_idx;
+ }
+
+ // if we find a page with a lower use sequence, that is older.
+ if ((oldest_seq == 0) || (oldest_seq > m_mru[current_idx].use_sequence)) {
+ oldest_seq = m_mru[current_idx].use_sequence;
+ oldest_idx = current_idx;
+ }
+
+ current_idx++;
+
+ // wrap around?
+ if (current_idx >= m_mru_num_pages)
+ current_idx = 0;
+ }
+#ifdef LOG_CACHE_OPS
+ oss << "TrcMemAccCache:: ALI-evict and allocate old page: [page: " << std::dec << oldest_idx << "]\n";
+ logMsg(oss.str());
+#endif
+ return oldest_idx;
+}
+
+void TrcMemAccCache::incSequence()
+{
+ m_mru[m_mru_idx].use_sequence = m_mru_sequence++;
+ if (m_mru_sequence == 0) {
+ // wrapped which throws out the oldest algorithm - oldest will now appear newer - so not evicted.
+ // arbitrarily re-sequence all in use..
+ m_mru_sequence = 1;
+ for (int i = 0; i < m_mru_num_pages; i++)
+ if (m_mru[i].use_sequence != 0)
+ m_mru[i].use_sequence = m_mru_sequence++;
+
+ // ensure newest still newest...
+ m_mru[m_mru_idx].use_sequence = m_mru_sequence++;
+ }
+}
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;
+ std::string memSpaceStr;
#endif
if (m_bCacheEnabled)
{
- if (blockInCache(address, reqBytes))
+ if (blockInCache(address, reqBytes, trcID))
{
bytesRead = reqBytes;
memcpy(byteBuffer, &m_mru[m_mru_idx].data[address - m_mru[m_mru_idx].st_addr], reqBytes);
+ incSequence();
#ifdef LOG_CACHE_OPS
- oss << "TrcMemAccCache:: hit [page: " << std::dec << m_mru_idx << "[addr:0x" << std::hex << address << ", bytes: " << std::dec << reqBytes << "]\n";
+ oss << "TrcMemAccCache:: hit {page: " << std::dec << m_mru_idx << "; seq: " << m_mru[m_mru_idx].use_sequence << " CSID: " << std::hex << (int)m_mru[m_mru_idx].trcID;
+ oss << "} [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]);
+ m_mru_idx = findNewPage();
+ m_mru[m_mru_idx].valid_len = p_accessor->readBytes(address, mem_space, trcID, m_mru_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)
+ if (m_mru[m_mru_idx].valid_len > m_mru_page_size)
{
m_mru[m_mru_idx].valid_len = 0; // set to nothing returned.
err = OCSD_ERR_MEM_ACC_BAD_LEN;
@@ -102,25 +297,24 @@ ocsd_err_t TrcMemAccCache::readBytesFromCache(TrcMemAccessorBase *p_accessor, co
if (m_mru[m_mru_idx].valid_len > 0)
{
- // got some data - so save the
+ // got some data - so save the details
m_mru[m_mru_idx].st_addr = address;
+ m_mru[m_mru_idx].trcID = trcID;
+ incSequence();
// log the run length hit counts
SET_MAX_RL(m_mru_idx);
#ifdef LOG_CACHE_OPS
+ TrcMemAccessorBase::getMemAccSpaceString(memSpaceStr, mem_space);
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";
+ oss << "TrcMemAccCache:: ALI-load {page: " << std::dec << m_mru_idx << "; seq: " << m_mru[m_mru_idx].use_sequence << " CSID: " << std::hex << (int)m_mru[m_mru_idx].trcID;
+ oss << "} [mem space: " << memSpaceStr << ", 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;
+ INC_PAGES();
- if (blockInPage(address, reqBytes)) /* check we got the data we needed */
+ if (blockInPage(address, reqBytes, trcID)) /* 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);
@@ -130,7 +324,7 @@ ocsd_err_t TrcMemAccCache::readBytesFromCache(TrcMemAccessorBase *p_accessor, co
{
#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";
+ 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();
@@ -142,6 +336,42 @@ ocsd_err_t TrcMemAccCache::readBytesFromCache(TrcMemAccessorBase *p_accessor, co
return err;
}
+void TrcMemAccCache::invalidateAll()
+{
+#ifdef LOG_CACHE_OPS
+ std::ostringstream oss;
+ oss << "TrcMemAccCache:: ALI-invalidate All\n";
+ logMsg(oss.str());
+#endif
+
+ for (int i = 0; i < m_mru_num_pages; i++)
+ clearPage(&m_mru[i]);
+ m_mru_idx = 0;
+}
+
+void TrcMemAccCache::invalidateByTraceID(int8_t trcID)
+{
+#ifdef LOG_CACHE_OPS
+ std::ostringstream oss;
+ oss << "TrcMemAccCache:: ALI-invalidate by ID request {CSID: " << std::hex << (int)trcID << "}\n";
+ logMsg(oss.str());
+#endif
+
+ for (int i = 0; i < m_mru_num_pages; i++)
+ {
+ if (m_mru[i].trcID == trcID)
+ {
+#ifdef LOG_CACHE_OPS
+ oss.str("");
+ oss << "TrcMemAccCache:: ALI-invalidate page {page: " << std::dec << i << "; seq: " << m_mru[i].use_sequence << " CSID: " << std::hex << (int)m_mru[i].trcID;
+ oss << "} [addr:0x" << std::hex << m_mru[i].st_addr << ", bytes: " << std::dec << m_mru[i].valid_len << "]\n";
+ logMsg(oss.str());
+#endif
+ clearPage(&m_mru[i]);
+ }
+ }
+}
+
void TrcMemAccCache::logMsg(const std::string &szMsg)
{
if (m_err_log)
@@ -158,9 +388,10 @@ 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";
+ oss << "TrcMemAccCache:: cache performance: Page Size: 0x" << std::hex << m_mru_page_size << "; Number of Pages: " << std::dec << m_mru_num_pages << "\n";
+ oss << "Cache hits(" << std::dec << m_hits << "), misses(" << m_misses << "), new pages(" << m_pages << ")\n";
logMsg(oss.str());
- for (int i = 0; i < MEM_ACC_CACHE_MRU_SIZE; i++)
+ for (int i = 0; i < m_mru_num_pages; i++)
{
if (m_hit_rl_max[i] < m_hit_rl[i])
m_hit_rl_max[i] = m_hit_rl[i];
@@ -172,5 +403,4 @@ void TrcMemAccCache::logAndClearCounts()
#endif
}
-
/* End of File trc_mem_acc_cache.cpp */
diff --git a/decoder/source/mem_acc/trc_mem_acc_mapper.cpp b/decoder/source/mem_acc/trc_mem_acc_mapper.cpp
index 72efe77..9327f56 100644
--- a/decoder/source/mem_acc/trc_mem_acc_mapper.cpp
+++ b/decoder/source/mem_acc/trc_mem_acc_mapper.cpp
@@ -40,17 +40,12 @@
/* 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) :
@@ -59,9 +54,6 @@ 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()
@@ -74,6 +66,17 @@ void TrcMemAccMapper::setErrorLog(ITraceErrorLog *err_log_i)
m_cache.setErrorLog(err_log_i);
}
+ocsd_err_t TrcMemAccMapper::enableCaching(bool bEnable)
+{
+ return m_cache.enableCaching(bEnable);
+}
+
+// set cache page size and number of pages (max 4096 size, 256 pages)
+ocsd_err_t TrcMemAccMapper::setCacheSizes(uint16_t page_size, int num_pages)
+{
+ return m_cache.setCacheSizes(page_size, num_pages);
+}
+
// 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)
{
@@ -88,7 +91,7 @@ ocsd_err_t TrcMemAccMapper::ReadTargetMemory(const ocsd_vaddr_t address, const u
// found a new accessor - invalidate any cache entries used by the previous one.
if (m_cache.enabled() && bReadFromCurr)
- m_cache.invalidateAll();
+ m_cache.invalidateByTraceID(cs_trace_id);
}
/* if bReadFromCurr then we know m_acc_curr is set */
@@ -119,12 +122,10 @@ ocsd_err_t TrcMemAccMapper::ReadTargetMemory(const ocsd_vaddr_t address, const u
return err;
}
-void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t /* cs_trace_id */)
-{
- // default mapper does not use cs_trace_id for cache invalidation.
+void TrcMemAccMapper::InvalidateMemAccCache(const uint8_t cs_trace_id)
+{
if (m_cache.enabled())
- m_cache.invalidateAll();
- m_acc_curr = 0;
+ m_cache.invalidateByTraceID(cs_trace_id);
}
void TrcMemAccMapper::RemoveAllAccessors()
@@ -170,7 +171,6 @@ void TrcMemAccMapper::LogWarn(const ocsd_err_t err, const std::string &msg)
}
}
-
/************************************************************************************/
/* mappers global address space class - no differentiation in core trace IDs */
/************************************************************************************/