#ifndef UPDATE_TAB_H_ #define UPDATE_TAB_H_ #include #include #include #include "arithmetics.h" //////////////////////////////////////////////////////////////////////// // An update tab entry //////////////////////////////////////////////////////////////////////// class UpdateTabEntry { typedef uint32_t size_t; typedef sc_dt::sc_uint<40> addr_t; public: bool valid; // It is a valid pending transaction bool update; // It is an update transaction bool brdcast; // It is a broadcast invalidate bool rsp; // Response to the initiator required bool ack; // Acknowledge to the CONFIG FSM required size_t srcid; // The srcid of the initiator which wrote the data size_t trdid; // The trdid of the initiator which wrote the data size_t pktid; // The pktid of the initiator which wrote the data addr_t nline; // The identifier of the cache line size_t count; // The number of acknowledge responses to receive UpdateTabEntry() { valid = false; update = false; brdcast = false; rsp = false; ack = false; srcid = 0; trdid = 0; pktid = 0; nline = 0; count = 0; } UpdateTabEntry(bool i_valid, bool i_update, bool i_brdcast, bool i_rsp, bool i_ack, size_t i_srcid, size_t i_trdid, size_t i_pktid, addr_t i_nline, size_t i_count) { valid = i_valid; update = i_update; brdcast = i_brdcast; rsp = i_rsp; ack = i_ack; srcid = i_srcid; trdid = i_trdid; pktid = i_pktid; nline = i_nline; count = i_count; } UpdateTabEntry(const UpdateTabEntry &source) { valid = source.valid; update = source.update; brdcast = source.brdcast; rsp = source.rsp; ack = source.ack; srcid = source.srcid; trdid = source.trdid; pktid = source.pktid; nline = source.nline; count = source.count; } //////////////////////////////////////////////////// // The init() function initializes the entry /////////////////////////////////////////////////// void init() { valid = false; update = false; brdcast = false; rsp = false; ack = false; srcid = 0; trdid = 0; pktid = 0; nline = 0; count = 0; } //////////////////////////////////////////////////////////////////// // The copy() function copies an existing entry // Its arguments are : // - source : the update tab entry to copy //////////////////////////////////////////////////////////////////// void copy(const UpdateTabEntry &source) { valid = source.valid; update = source.update; brdcast = source.brdcast; rsp = source.rsp; ack = source.ack; srcid = source.srcid; trdid = source.trdid; pktid = source.pktid; nline = source.nline; count = source.count; } //////////////////////////////////////////////////////////////////// // The print() function prints the entry //////////////////////////////////////////////////////////////////// void print() { std::cout << " val = " << std::dec << valid << " / updt = " << update << " / bc = " << brdcast << " / rsp = " << rsp << " / ack = " << ack << " / count = " << count << " / srcid = " << std::hex << srcid << " / trdid = " << trdid << " / pktid = " << pktid << " / nline = " << nline << std::endl; } }; //////////////////////////////////////////////////////////////////////// // The update tab //////////////////////////////////////////////////////////////////////// class UpdateTab{ typedef uint64_t addr_t; private: size_t size_tab; std::vector tab; public: UpdateTab() : tab(0) { size_tab = 0; } UpdateTab(size_t size_tab_i) : tab(size_tab_i) { size_tab = size_tab_i; } //////////////////////////////////////////////////////////////////// // The size() function returns the size of the tab //////////////////////////////////////////////////////////////////// const size_t size() { return size_tab; } //////////////////////////////////////////////////////////////////// // The print() function diplays the tab content //////////////////////////////////////////////////////////////////// void print() { std::cout << "UPDATE TABLE Content" << std::endl; for (size_t i = 0; i < size_tab; i++) { std::cout << "[" << std::dec << i << "] "; tab[i].print(); } return; } ///////////////////////////////////////////////////////////////////// // The init() function initializes the tab ///////////////////////////////////////////////////////////////////// void init() { for (size_t i = 0; i < size_tab; i++) { tab[i].init(); } } ///////////////////////////////////////////////////////////////////// // The reads() function reads an entry // Arguments : // - entry : the entry to read // This function returns a copy of the entry. ///////////////////////////////////////////////////////////////////// UpdateTabEntry read(size_t entry) { assert(entry < size_tab && "Bad Update Tab Entry"); return UpdateTabEntry(tab[entry]); } /////////////////////////////////////////////////////////////////////////// // The set() function writes an entry in the Update Table // Arguments : // - update : transaction type (bool) // - srcid : srcid of the initiator // - trdid : trdid of the initiator // - pktid : pktid of the initiator // - count : number of expected responses // - index : (return argument) index of the selected entry // This function returns true if the write successed (an entry was empty). /////////////////////////////////////////////////////////////////////////// bool set(const bool update, const bool brdcast, const bool rsp, const bool ack, const size_t srcid, const size_t trdid, const size_t pktid, const addr_t nline, const size_t count, size_t &index) { for (size_t i = 0; i < size_tab; i++) { if (!tab[i].valid) { tab[i].valid = true; tab[i].update = update; tab[i].brdcast = brdcast; tab[i].rsp = rsp; tab[i].ack = ack; tab[i].srcid = (size_t) srcid; tab[i].trdid = (size_t) trdid; tab[i].pktid = (size_t) pktid; tab[i].nline = (addr_t) nline; tab[i].count = (size_t) count; index = i; return true; } } return false; } // end set() ///////////////////////////////////////////////////////////////////// // The decrement() function decrements the counter for a given entry. // Arguments : // - index : the index of the entry // - counter : (return argument) value of the counter after decrement // This function returns true if the entry is valid. ///////////////////////////////////////////////////////////////////// bool decrement(const size_t index, size_t &counter) { assert((index < size_tab) && "Bad Update Tab Entry"); if (tab[index].valid) { tab[index].count--; counter = tab[index].count; return true; } else { return false; } } ///////////////////////////////////////////////////////////////////// // The is_full() function returns true if the table is full ///////////////////////////////////////////////////////////////////// bool is_full() { for (size_t i = 0; i < size_tab; i++) { if (!tab[i].valid) { return false; } } return true; } ///////////////////////////////////////////////////////////////////// // The is_not_empty() function returns true if the table is not empty ///////////////////////////////////////////////////////////////////// bool is_not_empty() { for (size_t i = 0; i < size_tab; i++) { if (tab[i].valid) { return true; } } return false; } ///////////////////////////////////////////////////////////////////// // The need_rsp() function returns the need of a response // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// bool need_rsp(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); return tab[index].rsp; } ///////////////////////////////////////////////////////////////////// // The need_ack() function returns the need of an acknowledge // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// bool need_ack(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); return tab[index].ack; } ///////////////////////////////////////////////////////////////////// // The is_brdcast() function returns the transaction type // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// bool is_brdcast(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); return tab[index].brdcast; } ///////////////////////////////////////////////////////////////////// // The is_update() function returns the transaction type // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// bool is_update(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); return tab[index].update; } ///////////////////////////////////////////////////////////////////// // The srcid() function returns the srcid value // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// size_t srcid(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); return tab[index].srcid; } ///////////////////////////////////////////////////////////////////// // The trdid() function returns the trdid value // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// size_t trdid(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); return tab[index].trdid; } ///////////////////////////////////////////////////////////////////// // The pktid() function returns the pktid value // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// size_t pktid(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); return tab[index].pktid; } ///////////////////////////////////////////////////////////////////// // The nline() function returns the nline value // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// addr_t nline(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); return tab[index].nline; } ///////////////////////////////////////////////////////////////////// // The search_inval() function returns the index of the entry in UPT // Arguments : // - nline : the line number of the entry in the directory ///////////////////////////////////////////////////////////////////// bool search_inval(const addr_t nline, size_t &index) { size_t i; for (i = 0; i < size_tab; i++) { if ((tab[i].nline == nline) and tab[i].valid and not tab[i].update) { index = i; return true; } } return false; } ///////////////////////////////////////////////////////////////////// // The read_nline() function returns the index of the entry in UPT // Arguments : // - nline : the line number of the entry in the directory ///////////////////////////////////////////////////////////////////// bool read_nline(const addr_t nline, size_t &index) { size_t i; for (i = 0; i < size_tab; i++) { if ((tab[i].nline == nline) and tab[i].valid) { index = i; return true; } } return false; } ///////////////////////////////////////////////////////////////////// // The clear() function erases an entry of the tab // Arguments : // - index : the index of the entry ///////////////////////////////////////////////////////////////////// void clear(const size_t index) { assert(index < size_tab && "Bad Update Tab Entry"); tab[index].valid = false; return; } }; #endif // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4