#ifndef CACHE_H #define CACHE_H #include #include #include #include "cache_multilevel.h" #include "cache_onelevel.h" #include "type_req_cache.h" #include "type_rsp_cache.h" using namespace std; using namespace hierarchy_memory::cache::cache_multilevel; namespace hierarchy_memory { namespace cache { typedef enum { INSTRUCTION_CACHE , DATA_CACHE } cache_t; class param_t { public : const char * name ; public : uint32_t nb_entity ; public : cache_multilevel::param_t * param_icache_dedicated; // 1 each entity public : cache_multilevel::param_t * param_dcache_dedicated; // 1 each entity public : cache_multilevel::param_t param_cache_shared ; // 1 to all entity and I/D is unify public : param_t () {}; public : param_t (const char * name , uint32_t nb_entity , cache_multilevel::param_t * param_icache_dedicated, cache_multilevel::param_t * param_dcache_dedicated, cache_multilevel::param_t param_cache_shared ) : name (name) { this->name = name ; this->nb_entity = nb_entity ; this->param_icache_dedicated = param_icache_dedicated ; this->param_dcache_dedicated = param_dcache_dedicated ; this->param_cache_shared = param_cache_shared ; } friend ostream& operator<< (ostream& output_stream, const param_t & x) { output_stream << "<" << x.name << ">" << endl << " * nb_entity : " << x.nb_entity << endl; for (uint32_t it = 0; it < x.nb_entity; it ++) output_stream << x.param_icache_dedicated [it] << endl; for (uint32_t it = 0; it < x.nb_entity; it ++) output_stream << x.param_dcache_dedicated [it] << endl; output_stream << x.param_cache_shared << endl; return output_stream; } };//end param_t class Cache { private : char * name ; protected: const uint32_t nb_entity ; protected: uint32_t nb_iport ; protected: uint32_t nb_dport ; protected: Cache_Multilevel ** icache_dedicated; protected: Cache_Multilevel ** dcache_dedicated; protected: Cache_Multilevel * cache_shared ; //*****[ constructor ]***** public : Cache (param_t param): nb_entity (param.nb_entity) { uint32_t size_name = strlen(param.name)+1; name = new char [size_name]; strncpy(name,param.name,size_name); cache_shared = new Cache_Multilevel (param.param_cache_shared); icache_dedicated = new Cache_Multilevel * [nb_entity]; dcache_dedicated = new Cache_Multilevel * [nb_entity]; nb_iport = 0; nb_dport = 0; for (uint32_t it = 0; it < nb_entity ; it++) { icache_dedicated [it] = new Cache_Multilevel (param.param_icache_dedicated[it]); dcache_dedicated [it] = new Cache_Multilevel (param.param_dcache_dedicated[it]); nb_iport += param.param_icache_dedicated[it].nb_port; nb_dport += param.param_dcache_dedicated[it].nb_port; } information(); }; //*****[ destructor ]***** public : ~Cache () { for (uint32_t it = 0; it < nb_entity ; it++) { delete icache_dedicated [it]; delete dcache_dedicated [it]; } delete cache_shared ; }; //*****[ reset ]***** void reset () { cache_shared -> reset(); // Reset buffer of respons for (uint32_t it = 0; it < nb_entity; it++) { icache_dedicated [it] ->reset(); dcache_dedicated [it] ->reset(); } }//end reset //*****[ transition ]***** void transition() { cache_shared -> transition(); // Transition buffer of respons for (uint32_t it = 0; it < nb_entity; it++) { icache_dedicated [it] ->transition(); dcache_dedicated [it] ->transition(); } }//end transition //*****[ range_port ]***** public : uint32_t range_port (cache_t type_cache, uint32_t num_entity) { uint32_t nb_port_dedicated = 0; if (type_cache == INSTRUCTION_CACHE) for (uint32_t it = 1; it < num_entity; it++ ) nb_port_dedicated += icache_dedicated [it]->nb_port; else { nb_port_dedicated = nb_iport; for (uint32_t it = 1; it < num_entity; it++) nb_port_dedicated += dcache_dedicated [it]->nb_port; } return nb_port_dedicated; } //*****[ latence ]***** // Return the time to have the data // latence is call on the same port in a single cycle, only the last access is save // { NOTE } : type_cache = 0 : icache, 1 : dcache public : uint32_t latence (cache_t type_cache, uint32_t num_entity, uint32_t num_port , uint32_t address , uint32_t trdid , type_req_cache_t type , direction_req_cache_t dir ) { if (num_entity >= nb_entity) { cerr << " {ERROR} num_entity ("<< num_entity << ") can be >= nb_entity (" << nb_entity << ")" << endl; exit (1); } Cache_Multilevel * cache; if (type_cache == INSTRUCTION_CACHE) cache = icache_dedicated [num_entity]; else cache = dcache_dedicated [num_entity]; if (num_port >= cache->nb_port) { cerr << " {ERROR} num_port ("<< num_port << ") can be >= nb_port (" << cache->nb_port << ")" << endl; exit (1); } // Make a access with this level "dedicated" access_t access_dedicated = cache->access(num_port,address,trdid,type,dir); // cout << "access_dedicated : " << access_dedicated << endl; if (access_dedicated.hit == MISS) { // Make a access with this level "shared" access_t access_shared = cache_shared->access(range_port (type_cache,num_entity)+num_port,address,trdid,type,dir); // cout << "access_shared : " << access_shared << endl; cache_shared->update_access (access_shared); access_dedicated.last_nb_level = cache->nb_level; // Update all cache access_dedicated.latence += access_shared.latence; // cout << "access_dedicated (after) : " << access_dedicated << endl; } cache->update_access (access_dedicated); return access_dedicated.latence; } //*****[ information ]***** public : void information (void) { cout << "<" << name << ">" << endl; for (uint32_t it = 0; it < nb_entity; it ++) icache_dedicated [it]->information(); for (uint32_t it = 0; it < nb_entity; it ++) dcache_dedicated [it]->information(); cache_shared->information(); } friend ostream& operator<< (ostream& output_stream, const Cache & x) { output_stream << "<" << x.name << ">" << endl; for (uint32_t it = 0; it < x.nb_entity; it ++) output_stream << *x.icache_dedicated [it] << endl; for (uint32_t it = 0; it < x.nb_entity; it ++) output_stream << *x.dcache_dedicated [it] << endl; output_stream << *x.cache_shared << endl; return output_stream; } };//end Cache };}; #endif //!CACHE_H