diff options
author | Mike Leach <mike.leach@linaro.org> | 2023-11-06 20:58:04 +0000 |
---|---|---|
committer | Mike Leach <mike.leach@linaro.org> | 2023-12-18 14:57:54 +0000 |
commit | 8f3a7b29f2faff905380ad5e9a77bd5d82f86773 (patch) | |
tree | 7496cfafdc87990fed910ee949eec0edae783a49 | |
parent | 12eb668a24fb36233db62c4fd114504193635abe (diff) | |
download | OpenCSD-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.h | 6 | ||||
-rw-r--r-- | decoder/include/mem_acc/trc_mem_acc_cache.h | 138 | ||||
-rw-r--r-- | decoder/include/mem_acc/trc_mem_acc_mapper.h | 6 | ||||
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_base.cpp | 42 | ||||
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_cache.cpp | 270 | ||||
-rw-r--r-- | decoder/source/mem_acc/trc_mem_acc_mapper.cpp | 30 |
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 */ /************************************************************************************/ |