#ifndef SOCLIB_CABA_MEM_CACHE_DIRECTORY_H #define SOCLIB_CABA_MEM_CACHE_DIRECTORY_H #include #include #include #include "arithmetics.h" //#define RANDOM_EVICTION namespace soclib { namespace caba { enum mem_dir_entry_state_e { ENTRY_INVALID, ENTRY_EXCLUSIVE, ENTRY_SHARED, ENTRY_LOCKED }; using namespace sc_core; //////////////////////////////////////////////////////////////////////// // A LRU entry //////////////////////////////////////////////////////////////////////// class LruEntry { public: bool recent; void init() { recent=false; } }; // end class LruEntry //////////////////////////////////////////////////////////////////////// // An Owner //////////////////////////////////////////////////////////////////////// class Owner{ public: // Fields bool inst; // Is the owner an ICache ? size_t srcid; // The SRCID of the owner //////////////////////// // Constructors //////////////////////// Owner(bool i_inst, size_t i_srcid) { inst = i_inst; srcid = i_srcid; } Owner(const Owner &a) { inst = a.inst; srcid = a.srcid; } Owner() { inst = false; srcid = 0; } // end constructors }; // end class Owner //////////////////////////////////////////////////////////////////////// // A directory entry //////////////////////////////////////////////////////////////////////// class DirectoryEntry { typedef uint32_t tag_t; public: //bool valid; // entry valid //bool cache_coherent; // WB or WT policy size_t state; bool is_cnt; // directory entry is in counter mode bool dirty; // entry dirty bool lock; // entry locked tag_t tag; // tag of the entry size_t count; // number of copies Owner owner; // an owner of the line size_t ptr; // pointer to the next owner DirectoryEntry() { //valid = false; //cache_coherent= false; state = ENTRY_INVALID; is_cnt = false; dirty = false; lock = false; tag = 0; count = 0; owner.inst = 0; owner.srcid = 0; ptr = 0; } DirectoryEntry(const DirectoryEntry &source) { //valid = source.valid; //cache_coherent= source.cache_coherent; state = source.state; is_cnt = source.is_cnt; dirty = source.dirty; lock = source.lock; tag = source.tag; count = source.count; owner = source.owner; ptr = source.ptr; } ///////////////////////////////////////////////////////////////////// // The init() function initializes the entry ///////////////////////////////////////////////////////////////////// void init() { //valid = false; //cache_coherent = false; state = ENTRY_INVALID; is_cnt = false; dirty = false; lock = false; count = 0; } ///////////////////////////////////////////////////////////////////// // The copy() function copies an existing source entry to a target ///////////////////////////////////////////////////////////////////// void copy(const DirectoryEntry &source) { //valid = source.valid; //cache_coherent = source.cache_coherent; state = source.state; is_cnt = source.is_cnt; dirty = source.dirty; lock = source.lock; tag = source.tag; count = source.count; owner = source.owner; ptr = source.ptr; } //////////////////////////////////////////////////////////////////// // The print() function prints the entry //////////////////////////////////////////////////////////////////// void print() { std::cout //<< "Valid = " << valid //<< " ; COHERENCE = " << cache_coherent << " STATE = " << state << " ; IS COUNT = " << is_cnt << " ; Dirty = " << dirty << " ; Lock = " << lock << " ; Tag = " << std::hex << tag << std::dec << " ; Count = " << count << " ; Owner = " << owner.srcid << " " << owner.inst << " ; Pointer = " << ptr << std::endl; } }; // end class DirectoryEntry //////////////////////////////////////////////////////////////////////// // The directory //////////////////////////////////////////////////////////////////////// class CacheDirectory { typedef sc_dt::sc_uint<40> addr_t; typedef uint32_t data_t; typedef uint32_t tag_t; private: // Directory constants size_t m_ways; size_t m_sets; size_t m_words; size_t m_width; uint32_t lfsr; // the directory & lru tables DirectoryEntry **m_dir_tab; LruEntry **m_lru_tab; public: //////////////////////// // Constructor //////////////////////// CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width) { m_ways = ways; m_sets = sets; m_words = words; m_width = address_width; lfsr = -1; m_dir_tab = new DirectoryEntry*[sets]; for ( size_t i=0; i> (L2(m_words) + 2)) & (m_sets - 1); const tag_t tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2)); #undef L2 bool hit = false; for ( size_t i=0 ; i> (L2(m_words) + 2)) & (m_sets - 1); tag_t tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2)); #undef L2 for ( size_t way = 0 ; way < m_ways ; way++ ) { bool equal = ( m_dir_tab[set][way].tag == tag ); bool valid = (m_dir_tab[set][way].state != ENTRY_INVALID); if ( equal and valid ) { *ret_set = set; *ret_way = way; return DirectoryEntry(m_dir_tab[set][way]); } } return DirectoryEntry(); } // end read_neutral() ///////////////////////////////////////////////////////////////////// // The write function writes a new entry, // and updates the LRU bits if necessary. // Arguments : // - set : the set of the entry // - way : the way of the entry // - entry : the entry value ///////////////////////////////////////////////////////////////////// void write( const size_t &set, const size_t &way, const DirectoryEntry &entry) { assert( (set> 1) ^ ((-(lfsr & 1)) & 0xd0000001); way = lfsr % m_ways; return DirectoryEntry(m_dir_tab[set][way]); #endif // looking for a not locked and not recently used entry for(size_t i=0; i0 && "Memory Cache, HeapDirectory constructor : invalid size"); ptr_free = 0; full = false; m_heap_tab = new HeapEntry[size]; tab_size = size; } // end constructor ///////////////// // Destructor ///////////////// ~HeapDirectory(){ delete [] m_heap_tab; } // end destructor ///////////////////////////////////////////////////////////////////// // Global initialisation function ///////////////////////////////////////////////////////////////////// void init(){ ptr_free=0; full=false; for(size_t i=0; i< tab_size-1;i++){ m_heap_tab[i].next = i+1; } m_heap_tab[tab_size-1].next = tab_size-1; return; } ///////////////////////////////////////////////////////////////////// // The print() function prints a selected directory entry // Arguments : // - ptr : the pointer to the entry to print ///////////////////////////////////////////////////////////////////// void print(const size_t &ptr){ std::cout << "Heap, printing the entry : " << std::dec << ptr << std::endl; m_heap_tab[ptr].print(); } // end print() ///////////////////////////////////////////////////////////////////// // The print_list() function prints a list from selected directory entry // Arguments : // - ptr : the pointer to the first entry to print ///////////////////////////////////////////////////////////////////// void print_list(const size_t &ptr){ bool end = false; size_t ptr_temp = ptr; std::cout << "Heap, printing the list from : " << std::dec << ptr << std::endl; while(!end){ m_heap_tab[ptr_temp].print(); if(ptr_temp == m_heap_tab[ptr_temp].next) end = true; ptr_temp = m_heap_tab[ptr_temp].next; } } // end print_list() ///////////////////////////////////////////////////////////////////// // The is_full() function return true if the heap is full. ///////////////////////////////////////////////////////////////////// bool is_full(){ return full; } // end is_full() ///////////////////////////////////////////////////////////////////// // The next_free_ptr() function returns the pointer // to the next free entry. ///////////////////////////////////////////////////////////////////// size_t next_free_ptr(){ return ptr_free; } // end next_free_ptr() ///////////////////////////////////////////////////////////////////// // The next_free_entry() function returns // a copy of the next free entry. ///////////////////////////////////////////////////////////////////// HeapEntry next_free_entry(){ return HeapEntry(m_heap_tab[ptr_free]); } // end next_free_entry() ///////////////////////////////////////////////////////////////////// // The write_free_entry() function modify the next free entry. // Arguments : // - entry : the entry to write ///////////////////////////////////////////////////////////////////// void write_free_entry(const HeapEntry &entry){ m_heap_tab[ptr_free].copy(entry); } // end write_free_entry() ///////////////////////////////////////////////////////////////////// // The write_free_ptr() function writes the pointer // to the next free entry ///////////////////////////////////////////////////////////////////// void write_free_ptr(const size_t &ptr){ assert( (ptr * cache_line) { assert((set < m_sets ) && "Cache data error: Trying to read a wrong set" ); assert((way < m_ways ) && "Cache data error: Trying to read a wrong way" ); for (uint32_t word=0; word