/*************************************************************************** non-blocking write-back cache ***************************************************************************/ /* ***************************************************************************** BSD LICENSE ******************************************************************************** Copyright (c) 2006, Commissariat a l'Energie Atomique (CEA) & INRIA Authors: Sylvain Girbal (sylvain.girbal@inria.fr) Foundings: Partly founded with HiPEAC foundings All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 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. - Neither the name of the UNISIM 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 OWNER 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. ***************************************************************************** */ #undef TEST_LOAD_WRITEBACK #ifndef __MICROLIB_CACHE_WRAPPER_WBNBCDP_H__ #define __MICROLIB_CACHE_WRAPPER_WBNBCDP_H__ #include "unisim/unisim.h" //boveerle #include "ParameterCheck.h" #include "next.CacheWBNBCDP.h" #include "memreq.h" //eoveerle #include "mem_common.h" #include "common.h" #include "base/utility.h" #include "system/CacheContainer.h" #include "system/memory/cache/CacheCommon.h" #include //boveerle // To enable Emulator and Simulator communication ... #include //#include "plugins/os/linux/memory_flush_interface.hh" #include #include // Interface to Cacti 4 #include "power_estimation2/CactiCachePowerEstimator.h" #include "statistics/StatisticService.h" using full_system::utils::services::ServiceExport; using full_system::utils::services::ServiceImport; using full_system::utils::services::Service; using full_system::utils::services::Client; using full_system::utils::services::Object; using full_system::generic::memory::MemoryInterface; //using full_system::plugins::os::linux_os::MemoryFlushInterface; using full_system::plugins::SVGmemreqInterface; typedef ServiceExport< MemoryInterface > MI_ServiceExport; typedef ServiceImport< MemoryInterface > MI_ServiceImport; typedef Client< MemoryInterface > MI_Client; typedef Service< MemoryInterface > MI_Service; //eoveerle #include "system/memory/cache/microlib/systemc_wrapper.h" //boveerle //#include "system/memory/cache/microlib/CacheWBNBCDP.h" #include "CacheWBNBCDP.h" //eoveerle /** * \brief Single port, Blocking, WriteBack cache module */ template < class INSTRUCTION, // ReplacementPolicyType replacementPolicy, ///< replacement policy to apply (random, lru, pseudoLRU) int nCPUtoCacheDataPathSize, ///< max data size in bytes that can receive from the CPU int nCachetoCPUDataPathSize, ///< max data size in bytes that can send towards the CPU int nMemtoCacheDataPathSize, ///< max data size in bytes that can be received from the memory system int nCachetoMemDataPathSize, ///< max data size in bytes that can send towards the memory system, used in the case of write back policy int nLineSize, ///< size of a cache line in bytes int nCacheLines, ///< number of cache lines int nAssociativity, ///< associtivity level, if nAssoc==nCacheLines complete associative, if nAssoc==1 direct int nStages, ///< number of pipe stages, number of cycles. if nStages == 1 the cache is not pipelined int nDelay, ///< the delay cycles f each pipeline stage int nProg, int nMSHR, ///< maximum number of cache lines that can be waiting missing data int nMSHRRead, ///< maximum number of requests that can be waiting per nMSHR int nCDPPrefetchDepthThreshold, int nCDPEntries, //boveerle int nCPULineSize, //fixed parameters set here directly address_t nCDPCompareMask = 0xFFFFFFFFFF000000ULL, address_t nCDPFilterMask = 0x0000000000F00000ULL //eoveerle > class MicrolibCacheWrapperWBNBCDP : public module , public Client< MemoryInterface > , public Service< MemoryInterface > , public StatisticService {public: //boveerle int nLineSizeLowerLevel; int nCacheLinesLowerLevel; int nAssociativityLowerLevel; //eoveerle MicrolibCacheWBNBCDP < INSTRUCTION, // T 2, // nSources randomReplacementPolicy, nCPUtoCacheDataPathSize, nCachetoCPUDataPathSize, //boveerle nCPULineSize, // nCPULineSize //eoveerle nMemtoCacheDataPathSize, nCachetoMemDataPathSize, nLineSize, nCacheLines, nAssociativity, nStages, nDelay, 1, //nPorts nMSHR, nMSHRRead, nCDPPrefetchDepthThreshold, nCDPEntries, nCDPCompareMask, nCDPFilterMask > microlib_cache; /* --------------------------------------------------------------- */ /* Module ports - Service ports */ /* --------------------------------------------------------------- */ ServiceExport< MemoryInterface > syscall_MemExp; ServiceImport< MemoryInterface > syscall_MemImp; /* --------------------------------------------------------------- */ /* Module ports - UNISIM side */ /* --------------------------------------------------------------- */ inport < memreq < INSTRUCTION, nCPUtoCacheDataPathSize > > inCPU; ///< Input port for requests outport < memreq < INSTRUCTION, nCachetoCPUDataPathSize > > outCPU; ///< Output port for sending data toward CPU inport < memreq < INSTRUCTION, nMemtoCacheDataPathSize > > inMEM; ///< Input port for answers data outport < memreq < INSTRUCTION, nCachetoMemDataPathSize > > outMEM; ///< Output port for sending request toward memory hierarchy inclock inClock; ///< Clock (to be connected to the wrapped module clock) /* --------------------------------------------------------------- */ /* Module ports - MicroLib side */ /* --------------------------------------------------------------- */ // Input signals from the CPU sc_out TOinCPUtoCacheValid; sc_out TOinCPUtoCacheEnable; sc_out TOinCPUtoCacheInstruction; sc_out TOinCPUtoCacheCommand; ml_out_vector TOinCPUtoCacheData; sc_out TOinCPUtoCacheSize; sc_out TOinCPUtoCacheAddress; sc_out TOinCPUtoCacheTag; sc_out TOinCPUtoCacheAccept; //boveerle sc_out TOinCPUtoCacheReqSender; //eoveerle // Output signals to the CPU sc_in FROMoutCachetoCPUValid; sc_in FROMoutCachetoCPUInstruction; ml_in_vector FROMoutCachetoCPUData; sc_in FROMoutCachetoCPUSize; sc_in FROMoutCachetoCPUAddress; sc_in FROMoutCachetoCPUTag; sc_in FROMoutCachetoCPUEnable; sc_in FROMoutCachetoCPUAccept; //boveerle sc_in FROMoutCachetoCPUReqSender; //eoveerle // Input signals from the memory system sc_out TOinMemtoCacheValid; sc_out TOinMemtoCacheEnable; sc_out TOinMemtoCacheInstruction; ml_out_vector TOinMemtoCacheData; sc_out TOinMemtoCacheAddress; sc_out TOinMemtoCacheSize; sc_out TOinMemtoCacheTag; sc_out TOinMemtoCacheAccept; // Output signals to the memory system sc_in FROMoutCachetoMemValid; sc_in FROMoutCachetoMemInstruction; sc_in FROMoutCachetoMemCommand; ml_in_vector FROMoutCachetoMemData; sc_in FROMoutCachetoMemSize; sc_in FROMoutCachetoMemAddress; sc_in FROMoutCachetoMemTag; sc_in FROMoutCachetoMemEnable; sc_in FROMoutCachetoMemAccept; /* --------------------------------------------------------------- */ /* Microlib signals */ /* --------------------------------------------------------------- */ sc_signal sigTOinCPUtoCacheValid; sc_signal sigTOinCPUtoCacheEnable; sc_signal sigTOinCPUtoCacheInstruction; sc_signal sigTOinCPUtoCacheCommand; sc_signal < ByteArray > sigTOinCPUtoCacheData; sc_signal sigTOinCPUtoCacheSize; sc_signal sigTOinCPUtoCacheAddress; sc_signal sigTOinCPUtoCacheTag; sc_signal sigTOinCPUtoCacheAccept; //boveerle sc_signal sigTOinCPUtoCacheReqSender; //eoveerle sc_signal sigFROMoutCachetoCPUValid; sc_signal sigFROMoutCachetoCPUInstruction; sc_signal < ByteArray > sigFROMoutCachetoCPUData; sc_signal sigFROMoutCachetoCPUSize; sc_signal sigFROMoutCachetoCPUAddress; sc_signal sigFROMoutCachetoCPUTag; sc_signal sigFROMoutCachetoCPUAccept; sc_signal sigFROMoutCachetoCPUEnable; //boveerle sc_signal sigFROMoutCachetoCPUReqSender; //eoveerle sc_signal sigTOinMemtoCacheValid; sc_signal sigTOinMemtoCacheEnable; sc_signal sigTOinMemtoCacheInstruction; sc_signal < ByteArray > sigTOinMemtoCacheData; sc_signal sigTOinMemtoCacheAddress; sc_signal sigTOinMemtoCacheSize; sc_signal sigTOinMemtoCacheTag; sc_signal sigTOinMemtoCacheAccept; sc_signal sigFROMoutCachetoMemValid; sc_signal sigFROMoutCachetoMemInstruction; sc_signal sigFROMoutCachetoMemCommand; sc_signal < ByteArray > sigFROMoutCachetoMemData; sc_signal sigFROMoutCachetoMemSize; sc_signal sigFROMoutCachetoMemAddress; sc_signal sigFROMoutCachetoMemTag; sc_signal sigFROMoutCachetoMemAccept; sc_signal sigFROMoutCachetoMemEnable; /* --------------------------------------------------------------- */ /* Class constructor & destructor */ /* --------------------------------------------------------------- */ /** * \brief Module constructor */ MicrolibCacheWrapperWBNBCDP(const char *name) : module(name) , Object(name, 0) , Client< MemoryInterface >(name, this) , Service< MemoryInterface >(name, this) , microlib_cache("wrapped_cache") , syscall_MemExp("syscall_MemExp", this) , syscall_MemImp("syscall_MemImp", this) , StatisticService(name, this) { // Naming the interface ot enhance debugging //boveerle class_name = "CacheWBNBCDP"; //eoveerle inCPU.set_unisim_name(this,"inCPU"); inMEM.set_unisim_name(this,"inMEM"); outCPU.set_unisim_name(this,"outCPU"); outMEM.set_unisim_name(this,"outMEM"); // Set the sensitivity list of the module (UNISIM side) sensitive_method(on_CPU_data) << inCPU.data; sensitive_method(on_CPU_enable) << inCPU.enable; sensitive_method(on_CPU_accept) << outCPU.accept; sensitive_method(on_MEM_data) << inMEM.data; sensitive_method(on_MEM_enable) << inMEM.enable; sensitive_method(on_MEM_accept) << outMEM.accept; sensitive_neg_method(end_of_cycle) << inClock; // Set the sensitivity list of the module (microlib side) sensitive_method(on_MicroLib_to_CPU_data) << FROMoutCachetoCPUValid; sensitive_method(on_MicroLib_to_CPU_accept) << FROMoutCachetoCPUAccept; sensitive_method(on_MicroLib_to_CPU_enable) << FROMoutCachetoCPUEnable; sensitive_method(on_MicroLib_to_MEM_data) << FROMoutCachetoMemValid; sensitive_method(on_MicroLib_to_MEM_accept) << FROMoutCachetoMemAccept; sensitive_method(on_MicroLib_to_MEM_enable) << FROMoutCachetoMemEnable; // << outMEM.accept; //Port forwarding to the wrapped module microlib_cache.inClock(inClock); //Connecting microlib ports TOinCPUtoCacheValid(sigTOinCPUtoCacheValid); microlib_cache.inCPUtoCacheValid[0](sigTOinCPUtoCacheValid); TOinCPUtoCacheEnable(sigTOinCPUtoCacheEnable); microlib_cache.inCPUtoCacheEnable[0](sigTOinCPUtoCacheEnable); TOinCPUtoCacheInstruction(sigTOinCPUtoCacheInstruction); microlib_cache.inCPUtoCacheInstruction[0](sigTOinCPUtoCacheInstruction); TOinCPUtoCacheCommand(sigTOinCPUtoCacheCommand); microlib_cache.inCPUtoCacheCommand[0](sigTOinCPUtoCacheCommand); TOinCPUtoCacheData(sigTOinCPUtoCacheData); microlib_cache.inCPUtoCacheData[0](sigTOinCPUtoCacheData); TOinCPUtoCacheSize(sigTOinCPUtoCacheSize); microlib_cache.inCPUtoCacheSize[0](sigTOinCPUtoCacheSize); TOinCPUtoCacheAddress(sigTOinCPUtoCacheAddress); microlib_cache.inCPUtoCacheAddress[0](sigTOinCPUtoCacheAddress); TOinCPUtoCacheTag(sigTOinCPUtoCacheTag); microlib_cache.inCPUtoCacheTag[0](sigTOinCPUtoCacheTag); TOinCPUtoCacheAccept(sigTOinCPUtoCacheAccept); microlib_cache.inCPUtoCacheAccept[0](sigTOinCPUtoCacheAccept); //boveerle TOinCPUtoCacheReqSender(sigTOinCPUtoCacheReqSender); microlib_cache.inCPUtoCacheReqSender[0](sigTOinCPUtoCacheReqSender); //eoveerle FROMoutCachetoCPUValid(sigFROMoutCachetoCPUValid); microlib_cache.outCachetoCPUValid[0](sigFROMoutCachetoCPUValid); FROMoutCachetoCPUInstruction(sigFROMoutCachetoCPUInstruction); microlib_cache.outCachetoCPUInstruction[0](sigFROMoutCachetoCPUInstruction); FROMoutCachetoCPUData(sigFROMoutCachetoCPUData); microlib_cache.outCachetoCPUData[0](sigFROMoutCachetoCPUData); FROMoutCachetoCPUSize(sigFROMoutCachetoCPUSize); microlib_cache.outCachetoCPUSize[0](sigFROMoutCachetoCPUSize); FROMoutCachetoCPUAddress(sigFROMoutCachetoCPUAddress); microlib_cache.outCachetoCPUAddress[0](sigFROMoutCachetoCPUAddress); FROMoutCachetoCPUTag(sigFROMoutCachetoCPUTag); microlib_cache.outCachetoCPUTag[0](sigFROMoutCachetoCPUTag); FROMoutCachetoCPUAccept(sigFROMoutCachetoCPUAccept); microlib_cache.outCachetoCPUAccept[0](sigFROMoutCachetoCPUAccept); FROMoutCachetoCPUEnable(sigFROMoutCachetoCPUEnable); microlib_cache.outCachetoCPUEnable[0](sigFROMoutCachetoCPUEnable); //boveerle FROMoutCachetoCPUReqSender(sigFROMoutCachetoCPUReqSender); microlib_cache.outCachetoCPUReqSender[0](sigFROMoutCachetoCPUReqSender); //eoveerle TOinMemtoCacheValid(sigTOinMemtoCacheValid); microlib_cache.inMemtoCacheValid(sigTOinMemtoCacheValid); TOinMemtoCacheEnable(sigTOinMemtoCacheEnable); microlib_cache.inMemtoCacheEnable(sigTOinMemtoCacheEnable); TOinMemtoCacheInstruction(sigTOinMemtoCacheInstruction); microlib_cache.inMemtoCacheInstruction(sigTOinMemtoCacheInstruction); TOinMemtoCacheData(sigTOinMemtoCacheData); microlib_cache.inMemtoCacheData(sigTOinMemtoCacheData); TOinMemtoCacheAddress(sigTOinMemtoCacheAddress); microlib_cache.inMemtoCacheAddress(sigTOinMemtoCacheAddress); TOinMemtoCacheSize(sigTOinMemtoCacheSize); microlib_cache.inMemtoCacheSize(sigTOinMemtoCacheSize); TOinMemtoCacheTag(sigTOinMemtoCacheTag); microlib_cache.inMemtoCacheTag(sigTOinMemtoCacheTag); TOinMemtoCacheAccept(sigTOinMemtoCacheAccept); microlib_cache.inMemtoCacheAccept(sigTOinMemtoCacheAccept); FROMoutCachetoMemValid(sigFROMoutCachetoMemValid); microlib_cache.outCachetoMemValid(sigFROMoutCachetoMemValid); FROMoutCachetoMemInstruction(sigFROMoutCachetoMemInstruction); microlib_cache.outCachetoMemInstruction(sigFROMoutCachetoMemInstruction); FROMoutCachetoMemCommand(sigFROMoutCachetoMemCommand); microlib_cache.outCachetoMemCommand(sigFROMoutCachetoMemCommand); FROMoutCachetoMemData(sigFROMoutCachetoMemData); microlib_cache.outCachetoMemData(sigFROMoutCachetoMemData); FROMoutCachetoMemSize(sigFROMoutCachetoMemSize); microlib_cache.outCachetoMemSize(sigFROMoutCachetoMemSize); FROMoutCachetoMemAddress(sigFROMoutCachetoMemAddress); microlib_cache.outCachetoMemAddress(sigFROMoutCachetoMemAddress); FROMoutCachetoMemTag(sigFROMoutCachetoMemTag); microlib_cache.outCachetoMemTag(sigFROMoutCachetoMemTag); FROMoutCachetoMemAccept(sigFROMoutCachetoMemAccept); microlib_cache.outCachetoMemAccept(sigFROMoutCachetoMemAccept); FROMoutCachetoMemEnable(sigFROMoutCachetoMemEnable); microlib_cache.outCachetoMemEnable(sigFROMoutCachetoMemEnable); //boveerle // --- Registring parameters ---------------- parameters.add("nCPUtoCacheDataPathSize",nCPUtoCacheDataPathSize); parameters.add("nCachetoCPUDataPathSize",nCachetoCPUDataPathSize); //parameters.add("nCPULineSize",nCPULineSize); parameters.add("nMemtoCacheDataPathSize",nMemtoCacheDataPathSize); parameters.add("nCachetoMemDataPathSize",nCachetoMemDataPathSize); parameters.add("nLineSize",nLineSize,32,128); parameters.add("nCacheLines",nCacheLines,128,1048576); parameters.add("nAssociativity",nAssociativity,1,128); parameters.add("nStages",nStages,1,1); parameters.add("nDelay",nDelay,1,1); parameters.add("nProg",nProg); parameters.add("nMSHR",nMSHR,8,512); parameters.add("nMSHRRead",nMSHRRead,4,512); parameters.add("nCDPPrefetchDepthThreshold",nCDPPrefetchDepthThreshold,2,15); parameters.add("nCDPEntries",nCDPEntries,32,512); //eoveerle // --- Registring statistics ---------------- statistics.add("accesses",microlib_cache.accesses); statistics.add("accesses_read",microlib_cache.accesses_read); statistics.add("accesses_write",microlib_cache.accesses_write); statistics.add("accesses_prefetch",microlib_cache.accesses_prefetch); statistics.add("accesses_evict",microlib_cache.accesses_evict); statistics.add("hits",microlib_cache.hits); statistics.add("hits_read",microlib_cache.hits_read); statistics.add("hits_write",microlib_cache.hits_write); statistics.add("hits_prefetch",microlib_cache.hits_prefetch); statistics.add("hits_evict",microlib_cache.hits_evict); statistics.add("misses",microlib_cache.misses); statistics.add("misses_read",microlib_cache.misses_read); statistics.add("misses_write",microlib_cache.misses_write); statistics.add("misses_prefetch",microlib_cache.misses_prefetch); statistics.add("misses_evict",microlib_cache.misses_evict); statistics.add("writebacks",microlib_cache.writebacks); statistics.add("writebacks_read",microlib_cache.writebacks_read); statistics.add("writebacks_write",microlib_cache.writebacks_write); statistics.add("writebacks_prefetch",microlib_cache.writebacks_prefetch); statistics.add("writebacks_evict",microlib_cache.writebacks_evict); // --- Specific statistics ------------------- statistics.add("new_mshrs",microlib_cache.new_mshrs); statistics.add("existent_mshrs",microlib_cache.existent_mshrs); statistics.add("blocked_mshrs",microlib_cache.blocked_mshrs); statistics.add("rq_size",microlib_cache.rq_size); statistics.add("waiting_memory_bus",microlib_cache.waiting_memory_bus); // ------------------------------------------- } //boveerle int check_parameters() { bool invalid = false; invalid |= minmax_power_of_two(nLineSize, get_parameter("nLineSize").min(), get_parameter("nLineSize").max()); invalid |= minmax_power_of_two(nCacheLines, get_parameter("nCacheLines").min(), get_parameter("nCacheLines").max()); invalid |= ((int)get_parameter("nAssociativity").min() <= 0) || (nAssociativity < (int)get_parameter("nAssociativity").min()) || ( ((int)get_parameter("nAssociativity").max() < nAssociativity) && (nAssociativity != nCacheLines) ); invalid |= power_of_two(nCPUtoCacheDataPathSize); invalid |= power_of_two(nCachetoCPUDataPathSize); invalid |= power_of_two(nMemtoCacheDataPathSize); invalid |= power_of_two(nCachetoMemDataPathSize); invalid |= minmax_posint(nStages, get_parameter("nStages").min(), get_parameter("nStages").max()); invalid |= minmax_posint(nDelay, get_parameter("nDelay").min(), get_parameter("nDelay").max()); invalid |= minmax_power_of_two(nMSHR, get_parameter("nMSHR").min(), get_parameter("nMSHR").max()); invalid |= minmax_power_of_two(nMSHRRead, get_parameter("nMSHRRead").min(), get_parameter("nMSHRRead").max()); invalid |= minmax_posint(nCDPPrefetchDepthThreshold, get_parameter("nCDPPrefetchDepthThreshold").min(), get_parameter("nCDPPrefetchDepthThreshold").max()); invalid |= minmax_posint(nCDPEntries, get_parameter("nCDPEntries").min(), get_parameter("nCDPEntries").max()); // nCPULineSize equals the nLineSizeLowerLevel invalid |= (nCPULineSize != nLineSizeLowerLevel); // increasing linesizes cerr << invalid << endl; cerr << "nLineSizeLowerLevel:" << nLineSizeLowerLevel << " nCPULineSize:" << nCPULineSize << " nLineSize:" << nLineSize; invalid |= (nCPULineSize > nLineSize); // decreasing associativity invalid |= (nAssociativityLowerLevel!=0 && (nAssociativityLowerLevel < nAssociativity)); // starting from l2 no longer fully associative invalid |= (nAssociativityLowerLevel!=0 && nAssociativity==nCacheLines); // increasing cachesizes? invalid |= (nCacheLinesLowerLevel > nCacheLines); //datapath should be at most nLineSize -- dd. 2008-07-30 cerr << "DataPath=" << nMemtoCacheDataPathSize << " LineSize=" << nLineSize << endl; invalid |= (nMemtoCacheDataPathSize > nLineSize); return invalid; } bool get_latency(FILE *fp) { // if you want to validate the latency, return true // and you can generate a call for external LatencyEstimator int extra_tag_bits = 0, v=nCDPPrefetchDepthThreshold; while (v>0) { v = v >> 1; extra_tag_bits++; } fprintf(fp, \"echo CacheWBNBCDP\n"); fprintf(fp, "LatencyEstimator %d %d %d 1 0 0 0 1 %f %d 0 0 0 0 %d\n", (nAssociativity==nCacheLines ? nLineSize*nAssociativity : nLineSize*nAssociativity*nCacheLines), nLineSize, (nAssociativity==nCacheLines ? 0 : nAssociativity), TECHNOLOGY, nCachetoCPUDataPathSize, extra_tag_bits); return true; //otherwise return false return false; } bool get_area( FILE *fp) { // if you want to validate the area, return true // and you can generate a call for external AreaEstimator int extra_tag_bits = 0, v=nCDPPrefetchDepthThreshold; while (v>0) { v = v >> 1; extra_tag_bits++; } fprintf(fp, \"echo CacheWBNBCDP\n"); fprintf(fp, "AreaEstimator %d %d %d 1 0 0 0 1 %f %d 0 0 0 0 %d\n", (nAssociativity==nCacheLines ? nLineSize*nAssociativity : nLineSize*nAssociativity*nCacheLines), nLineSize, (nAssociativity==nCacheLines ? 0 : nAssociativity), TECHNOLOGY, nCachetoCPUDataPathSize, extra_tag_bits); return true; //otherwise return false return false; } //eoveerle /* --------------------------------------------------------------- */ /* UNISIM processes */ /* --------------------------------------------------------------- */ void end_of_cycle() { //INFO << microlib_cache.cacheQueue << endl; } /** * \brief Translate an incoming memory request from the CPU to a * microlib request to be send to a microlib cache. */ void on_CPU_data() { TOinCPUtoCacheValid = inCPU.data.something(); if(inCPU.data.something()) { memreq < INSTRUCTION, nCPUtoCacheDataPathSize > mr = inCPU.data; //INFO << "\e[31mCPU->\e[0m trying " << mr << endl; TOinCPUtoCacheInstruction = mr.instr; TOinCPUtoCacheSize = mr.size; TOinCPUtoCacheAddress = mr.address; TOinCPUtoCacheTag = mr.uid; TOinCPUtoCacheData.Write(mr.data.buffer,nCPUtoCacheDataPathSize); //boveerle TOinCPUtoCacheReqSender = mr.req_sender; //cerr << "["<name()<<"("<< timestamp()<<")]: \e[31mCPU->\e[0m trying " << mr << endl; //eoveerle switch(mr.command) { case memreq_types::cmd_READ: case memreq_types::cmd_READX: TOinCPUtoCacheCommand = READ_CACHE_COMMAND; break; case memreq_types::cmd_WRITE: TOinCPUtoCacheCommand = WRITE_CACHE_COMMAND; break; case memreq_types::cmd_PREFETCH: TOinCPUtoCacheCommand = PREFETCH_CACHE_COMMAND; break; case memreq_types::cmd_EVICT: TOinCPUtoCacheCommand = EVICT_CACHE_COMMAND; break; default: ERROR << "unhandled command: " << mr.command << endl; exit(1); } } } /** * \brief Forward the enable signal coming from the cpu to the MicroLib cache. */ void on_CPU_enable() { //if(inCPU.enable) INFO << "\e[1;31mCPU->\e[0m enabling " << inCPU.data << endl; TOinCPUtoCacheEnable = inCPU.enable; } /** * \brief Backward the accept signal coming from the cpu to the MicroLib cache. */ void on_CPU_accept() { TOinCPUtoCacheAccept = outCPU.accept; //INFO << __FUNCTION__ << ": " << outCPU.accept << endl; } /** * \brief */ void on_MEM_data() { if(inMEM.data.something()) { memreq < INSTRUCTION, nMemtoCacheDataPathSize > mr = inMEM.data; if(mr.req_sender==this) { //INFO << "\e[34mMEM->\e[0m trying " << mr << endl; TOinMemtoCacheValid = true; TOinMemtoCacheInstruction = mr.instr; TOinMemtoCacheSize = mr.size; TOinMemtoCacheAddress = mr.address; TOinMemtoCacheTag = mr.uid; TOinMemtoCacheData.Write(mr.data.buffer,nMemtoCacheDataPathSize); //boveerle //cerr << "["<name()<<"("<< timestamp()<<")]: \e[31mCPU->\e[0m on_MEM_data " << mr << endl; //eoveerle } else { TOinMemtoCacheValid = false; //INFO << "\e[1;30mMEM->\e[0m discarded " << mr << endl; } } else TOinMemtoCacheValid = false; } /** * \brief Forward the enable signal coming from the memory to the MicroLib cache. */ void on_MEM_enable() { if(inMEM.enable) { memreq < INSTRUCTION, nMemtoCacheDataPathSize > mr = inMEM.data; if(mr.req_sender==this) { TOinMemtoCacheEnable = true; //INFO << "\e[1;34mMEM->\e[0m enabling " << inMEM.data << endl; } else { TOinMemtoCacheEnable = false; } } else TOinMemtoCacheEnable = false; } /** * \brief Backward the accept signal coming from the memory to the MicroLib cache. */ void on_MEM_accept() { TOinMemtoCacheAccept=outMEM.accept; //INFO << __FUNCTION__ << ": " << outMEM.accept << endl; } /* --------------------------------------------------------------- */ /* MicroLib processes */ /* --------------------------------------------------------------- */ void on_MicroLib_to_CPU_data() { if(FROMoutCachetoCPUValid) { memreq < INSTRUCTION, nCachetoCPUDataPathSize > mr; mr.instr = FROMoutCachetoCPUInstruction; mr.size = FROMoutCachetoCPUSize; mr.address = FROMoutCachetoCPUAddress; mr.uid = FROMoutCachetoCPUTag; mr.data = FROMoutCachetoCPUData; mr.sender = this; mr.command = memreq_types::cmd_READ; // Only reads are coming back to the cpu mr.sender_type = memreq_types::sender_CACHE; mr.message_type = memreq_types::type_ANSWER; mr.req_sender = this; //boveerle mr.req_sender = FROMoutCachetoCPUReqSender; mr.sender = this; //cerr << "on_MicroLib_to_CPU_data \e[31m->CPU\e[0m trying " << mr << endl; //eoveerle //INFO << "\e[31m->CPU\e[0m trying " << mr << endl; outCPU.data = mr; } else { outCPU.data.nothing(); } } void on_MicroLib_to_CPU_accept() { inCPU.accept = FROMoutCachetoCPUAccept; //INFO << __FUNCTION__ << ": " << FROMoutCachetoCPUAccept << endl; } void on_MicroLib_to_CPU_enable() { outCPU.enable = FROMoutCachetoCPUEnable; //if(FROMoutCachetoCPUEnable) INFO << "\e[1;31m->CPU\e[0m enabling " << outMEM.data << endl; } void on_MicroLib_to_MEM_data() { if(FROMoutCachetoMemValid) { memreq < INSTRUCTION, nCachetoMemDataPathSize > mr; mr.instr = FROMoutCachetoMemInstruction; mr.address = FROMoutCachetoMemAddress; mr.size = FROMoutCachetoMemSize; mr.uid = FROMoutCachetoMemTag; mr.data = FROMoutCachetoMemData; switch(FROMoutCachetoMemCommand) { case WRITE_CACHE_COMMAND: mr.command = memreq_types::cmd_WRITE; break; case READ_CACHE_COMMAND: mr.command = memreq_types::cmd_READ; break; case PREFETCH_CACHE_COMMAND: mr.command = memreq_types::cmd_PREFETCH; break; case EVICT_CACHE_COMMAND: mr.command = memreq_types::cmd_EVICT; break; default: ERROR << "Unhandled command: " << FROMoutCachetoMemCommand << endl; exit(1); } mr.sender = this; mr.sender_type = memreq_types::sender_CACHE; mr.message_type = memreq_types::type_REQUEST; mr.req_sender = this; //INFO << "\e[34m->MEM\e[0m trying " << mr << endl; outMEM.data = mr; } else { outMEM.data.nothing(); } } void on_MicroLib_to_MEM_accept() { memreq < INSTRUCTION, nMemtoCacheDataPathSize > mr = inMEM.data; if(mr.req_sender==this) { inMEM.accept = FROMoutCachetoMemAccept; //INFO << __FUNCTION__ << ": " << FROMoutCachetoMemAccept << endl; } else { inMEM.accept=true; } } void on_MicroLib_to_MEM_enable() { outMEM.enable = FROMoutCachetoMemEnable; //if(FROMoutCachetoMemEnable) INFO << "\e[1;34m->MEM\e[0m enabling " << outMEM.data << endl; } /* --------------------------------------------------------------- */ /* Service methods */ /* --------------------------------------------------------------- */ void Reset() { } bool ReadMemory(address_t addr, void *buffer, uint32_t size) { // Fisrt, perform the read into the main memory. bool tmpres = syscall_MemImp->ReadMemory(addr,buffer,size); // Second, if is some lines are modified into the cache then update the buffer. for ( address_t word_addr=addr; word_addr<(addr+size); word_addr=((word_addr+nLineSize) & ~(nLineSize - 1)) ) { if (microlib_cache.cache.hit(word_addr)) { uint32_t t_set = microlib_cache.cache.getSet(word_addr); uint32_t t_line = microlib_cache.cache.getLine(word_addr); if (microlib_cache.cache.getValid(t_set,t_line)) if (microlib_cache.cache.getWrite(t_set,t_line)) { uint32_t t_size = nLineSize; address_t base_addr = (word_addr & ~(nLineSize - 1)); address_t write_offset = word_addr - addr; if ( (base_addr+nLineSize) < (word_addr+t_size) ) { t_size = t_size - (word_addr - base_addr); } if ( (addr+size) < (word_addr+t_size) ) { t_size = t_size - ( (word_addr+t_size) - (addr+size) ); } microlib_cache.cache.getCacheLineIndexed(((char *)buffer)+write_offset, t_set, t_line, word_addr-base_addr, t_size); } } } return tmpres; } bool WriteMemory(address_t addr, const void *buffer, uint32_t size) { // check for modified lines ... for ( address_t word_addr=addr; word_addr<(addr+size); word_addr=((word_addr+nLineSize) & ~(nLineSize - 1)) ) { address_t base_addr = (word_addr & ~(nLineSize - 1)); // Address of the cache line if (microlib_cache.cache.hit(word_addr)) { uint32_t t_set = microlib_cache.cache.getSet(word_addr); uint32_t t_line = microlib_cache.cache.getLine(word_addr); // For a write we don't check if the line is modified : we modify it ... // if (microlib_cache.cache.getWrite(t_set,t_line)) uint32_t t_size = nLineSize; address_t write_offset = word_addr - addr; if ( (base_addr+nLineSize) < (word_addr+t_size) ) { t_size = t_size - (word_addr - base_addr); } if ( (addr+size) < (word_addr+t_size) ) { // t_size = t_size - ((addr+size) - word_addr); t_size = t_size - ( (word_addr+t_size) - (addr+size) ); } microlib_cache.cache.setCacheLineIndexed(t_set, t_line, ((char *)buffer)+write_offset, word_addr-base_addr, t_size, true); // setCacheLineIndexed mark the line as modified. As we'll also forward the MemoryWrite to the memory, // let's reset the Write field. microlib_cache.cache.setWrite(t_set, t_line, false); // The mesi state goes to exclusive as other caches are flushed microlib_cache.cache.setMESI(t_set, t_line,MESI::state_EXCLUSIVE); //Send the modified cache line to the memory to ensure that line data not bellonging to the //buffer is also wrote-back. char line_buffer[nLineSize]; microlib_cache.cache.getCacheLine(line_buffer, t_set, t_line); syscall_MemImp->WriteMemory(base_addr,line_buffer,nLineSize); } } return syscall_MemImp->WriteMemory(addr,buffer,size); } //boveerle add introspection /** * \brief Service interface : initialization */ bool ClientIndependentSetup() { if(!syscall_MemImp) { ERROR << "syscall_MemImp service port is not connected. This connection is mandatory to perfrom syscalls !" << endl; return false; } // Retreive the linesize of the cache connected toward the CPU. Set it to zero if // directly connected to the CPU. try { nLineSizeLowerLevel = inCPU.get_connected_module()->get_parameter("nLineSize"); } catch (UnknownParameterException &e) { nLineSizeLowerLevel = 0; } //get parameters from the lower level cache, zero if directly connected to CPU try { nCacheLinesLowerLevel = inCPU.get_connected_module()->get_parameter("nCacheLines"); } catch (UnknownParameterException &e) { nCacheLinesLowerLevel = 0; } try { nAssociativityLowerLevel = inCPU.get_connected_module()->get_parameter("nAssociativity"); } catch (UnknownParameterException &e) { nAssociativityLowerLevel = 0; } return true; } //eoveerle }; #endif