#ifndef XRAM_TRANSACTION_H_ #define XRAM_TRANSACTION_H_ #include #include #include #include "arithmetics.h" #define DEBUG_XRAM_TRANSACTION 0 //////////////////////////////////////////////////////////////////////// // A transaction tab entry //////////////////////////////////////////////////////////////////////// class TransactionTabEntry { typedef sc_dt::sc_uint<64> wide_data_t; typedef sc_dt::sc_uint<40> addr_t; typedef uint32_t data_t; typedef uint32_t be_t; public: bool valid; // entry valid bool xram_read; // read request to XRAM addr_t nline; // index (zy) of the requested line size_t srcid; // processor requesting the transaction size_t trdid; // processor requesting the transaction size_t pktid; // processor requesting the transaction bool proc_read; // read request from processor size_t read_length; // length of the read (for the response) size_t word_index; // index of the first read word (for response) std::vector wdata; // write buffer (one cache line) std::vector wdata_be; // be for each data in the write buffer bool rerror; // error returned by xram data_t ll_key; // LL key returned by the llsc_global_table bool config; // transaction required by CONFIG FSM ///////////////////////////////////////////////////////////////////// // The init() function initializes the entry ///////////////////////////////////////////////////////////////////// void init() { valid = false; rerror = false; config = false; } ///////////////////////////////////////////////////////////////////// // The alloc() function initializes the vectors of an entry // The "n_words" argument is the number of words in a cache line. ///////////////////////////////////////////////////////////////////// void alloc(size_t n_words) { wdata_be.reserve((int) n_words); wdata.reserve((int) n_words); for (size_t i = 0; i < n_words; i++) { wdata_be.push_back(0); wdata.push_back(0); } } //////////////////////////////////////////////////////////////////// // The copy() function copies an existing entry //////////////////////////////////////////////////////////////////// void copy(const TransactionTabEntry &source) { valid = source.valid; xram_read = source.xram_read; nline = source.nline; srcid = source.srcid; trdid = source.trdid; pktid = source.pktid; proc_read = source.proc_read; read_length = source.read_length; word_index = source.word_index; wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end()); wdata.assign(source.wdata.begin(),source.wdata.end()); rerror = source.rerror; ll_key = source.ll_key; config = source.config; } //////////////////////////////////////////////////////////////////// // The print() function prints the entry identified by "index". //////////////////////////////////////////////////////////////////// void print(size_t index, size_t mode) { std::cout << " TRT[" << std::dec << index << "] " << " valid = " << valid << " / error = " << rerror << " / get = " << xram_read << " / config = " << config << std::hex << " / address = " << nline*4*wdata.size() << " / srcid = " << srcid << std::endl; if (mode) { std::cout << " trdid = " << trdid << " / pktid = " << pktid << std::dec << " / proc_read = " << proc_read << " / read_length = " << read_length << " / word_index = " << word_index << std::hex << " / ll_key = " << ll_key << std::endl; std::cout << " wdata = "; for (size_t i = 0; i < wdata.size(); i++) { std::cout << std::hex << wdata[i] << " / "; } std::cout << std::endl; } } ///////////////////////////////////////////////////////////////////// // Constructors ///////////////////////////////////////////////////////////////////// TransactionTabEntry() { wdata_be.clear(); wdata.clear(); valid = false; rerror = false; config = false; } TransactionTabEntry(const TransactionTabEntry &source) { valid = source.valid; xram_read = source.xram_read; nline = source.nline; srcid = source.srcid; trdid = source.trdid; pktid = source.pktid; proc_read = source.proc_read; read_length = source.read_length; word_index = source.word_index; wdata_be.assign(source.wdata_be.begin(), source.wdata_be.end()); wdata.assign(source.wdata.begin(), source.wdata.end()); rerror = source.rerror; ll_key = source.ll_key; config = source.config; } }; // end class TransactionTabEntry //////////////////////////////////////////////////////////////////////// // The transaction tab //////////////////////////////////////////////////////////////////////// class TransactionTab { typedef sc_dt::sc_uint<64> wide_data_t; typedef sc_dt::sc_uint<40> addr_t; typedef uint32_t data_t; typedef uint32_t be_t; private: const std::string tab_name; // the name for logs size_t size_tab; // the size of the tab data_t be_to_mask(be_t be) { data_t ret = 0; if (be & 0x1) { ret = ret | 0x000000FF; } if (be & 0x2) { ret = ret | 0x0000FF00; } if (be & 0x4) { ret = ret | 0x00FF0000; } if (be & 0x8) { ret = ret | 0xFF000000; } return ret; } public: TransactionTabEntry * tab; // The transaction tab //////////////////////////////////////////////////////////////////// // Constructors //////////////////////////////////////////////////////////////////// TransactionTab() { size_tab = 0; tab = NULL; } TransactionTab(const std::string &name, size_t n_entries, size_t n_words) : tab_name(name), size_tab(n_entries) { tab = new TransactionTabEntry[size_tab]; for (size_t i = 0; i < size_tab; i++) { tab[i].alloc(n_words); } } ~TransactionTab() { delete [] tab; } ///////////////////////////////////////////////////////////////////// // The size() function returns the size of the tab ///////////////////////////////////////////////////////////////////// size_t size() { return size_tab; } ///////////////////////////////////////////////////////////////////// // The init() function initializes the transaction tab entries ///////////////////////////////////////////////////////////////////// void init() { for (size_t i = 0; i < size_tab; i++) { tab[i].init(); } } ///////////////////////////////////////////////////////////////////// // The print() function prints TRT content. // Detailed content if detailed argument is non zero. ///////////////////////////////////////////////////////////////////// void print(size_t detailed = 0) { std::cout << " < TRT content in " << tab_name << " >" << std::endl; for (size_t id = 0; id < size_tab; id++) { tab[id].print( id , detailed ); } } ///////////////////////////////////////////////////////////////////// // The read() function returns a transaction tab entry. // Arguments : // - index : the index of the entry to read ///////////////////////////////////////////////////////////////////// TransactionTabEntry read(const size_t index) { assert((index < size_tab) and "MEMC ERROR: Invalid Transaction Tab Entry"); return tab[index]; } ///////////////////////////////////////////////////////////////////// // The full() function returns the state of the transaction tab // Arguments : // - index : (return argument) the index of an empty entry // The function returns true if the transaction tab is full ///////////////////////////////////////////////////////////////////// bool full(size_t & index) { for (size_t i = 0; i < size_tab; i++) { if (!tab[i].valid) { index = i; return false; } } return true; } ///////////////////////////////////////////////////////////////////// // The hit_read() function checks if an XRAM read transaction exists // for a given cache line. // Arguments : // - index : (return argument) the index of the hit entry, if there is // - nline : the index (zy) of the requested line // The function returns true if a read request has already been sent ////////////////////////////////////////////////////////////////////// bool hit_read(const addr_t nline,size_t &index) { for (size_t i = 0; i < size_tab; i++) { if ((tab[i].valid && (nline == tab[i].nline)) && (tab[i].xram_read)) { index = i; return true; } } return false; } /////////////////////////////////////////////////////////////////////// // The hit_write() function looks if an XRAM write transaction exists // for a given line. // Arguments : // - nline : the index (zy) of the requested line // The function returns true if a write request has already been sent /////////////////////////////////////////////////////////////////////// bool hit_write(const addr_t nline) { for (size_t i = 0; i < size_tab; i++) { if (tab[i].valid && (nline == tab[i].nline) && !(tab[i].xram_read)) { return true; } } return false; } ///////////////////////////////////////////////////////////////////// // The write_data_mask() function writes a vector of data (a line). // The data is written only if the corresponding bits are set // in the be vector. // Arguments : // - index : the index of the request in the transaction tab // - be : vector of be // - data : vector of data ///////////////////////////////////////////////////////////////////// void write_data_mask(const size_t index, const std::vector & be, const std::vector & data) { assert( (index < size_tab) and "MEMC ERROR: The selected entry is out of range in TRT write_data_mask()"); assert( (be.size() == tab[index].wdata_be.size()) and "MEMC ERROR: Bad be size in TRT write_data_mask()"); assert( (data.size() == tab[index].wdata.size()) and "MEMC ERROR: Bad data size in TRT write_data_mask()"); for (size_t i = 0; i < tab[index].wdata_be.size(); i++) { tab[index].wdata_be[i] = tab[index].wdata_be[i] | be[i]; data_t mask = be_to_mask(be[i]); tab[index].wdata[i] = (tab[index].wdata[i] & ~mask) | (data[i] & mask); } } ///////////////////////////////////////////////////////////////////// // The set() function registers a transaction (read or write) // to the XRAM in the transaction tab. // Arguments : // - index : index in the transaction tab // - xram_read : transaction type (read or write a cache line) // - nline : the index (zy) of the cache line // - srcid : srcid of the initiator that caused the transaction // - trdid : trdid of the initiator that caused the transaction // - pktid : pktid of the initiator that caused the transaction // - proc_read : does the initiator want a copy // - read_length : length of read (in case of processor read) // - word_index : index in the line (in case of single word read) // - data : the data to write (in case of write) // - data_be : the mask of the data to write (in case of write) // - ll_key : the ll key (if any) returned by the llsc_global_table // - config : transaction required by config FSM ///////////////////////////////////////////////////////////////////// void set(const size_t index, const bool xram_read, const addr_t nline, const size_t srcid, const size_t trdid, const size_t pktid, const bool proc_read, const size_t read_length, const size_t word_index, const std::vector & data_be, const std::vector & data, const data_t ll_key = 0, const bool config = false) { assert((index < size_tab) and "MEMC ERROR: The selected entry is out of range in TRT set()"); assert((data_be.size()==tab[index].wdata_be.size()) and "MEMC ERROR: Bad data_be argument in TRT set()"); assert((data.size()==tab[index].wdata.size()) and "MEMC ERROR: Bad data argument in TRT set()"); tab[index].valid = true; tab[index].xram_read = xram_read; tab[index].nline = nline; tab[index].srcid = srcid; tab[index].trdid = trdid; tab[index].pktid = pktid; tab[index].proc_read = proc_read; tab[index].read_length = read_length; tab[index].word_index = word_index; tab[index].ll_key = ll_key; tab[index].config = config; for (size_t i = 0; i < tab[index].wdata.size(); i++) { tab[index].wdata_be[i] = data_be[i]; tab[index].wdata[i] = data[i]; } } ///////////////////////////////////////////////////////////////////// // The write_rsp() function writes two 32 bits words of the response // to a XRAM read transaction. // The BE field in TRT is taken into account. // Arguments : // - index : index of the entry in TRT // - word : index of the 32 bits word in the line // - data : 64 bits value (first data right) ///////////////////////////////////////////////////////////////////// void write_rsp(const size_t index, const size_t word, const wide_data_t data, const bool rerror) { data_t value; data_t mask; assert((index < size_tab) and "MEMC ERROR: The selected entry is out of range in TRT write_rsp()"); assert((word < tab[index].wdata_be.size()) and "MEMC ERROR: Bad word index in TRT write_rsp()"); assert((tab[index].valid) and "MEMC ERROR: TRT entry not valid in TRT write_rsp()"); assert((tab[index].xram_read ) and "MEMC ERROR: TRT entry is not a GET in TRT write_rsp()"); if (rerror) { tab[index].rerror = true; return; } // first 32 bits word value = (data_t) data; mask = be_to_mask(tab[index].wdata_be[word]); tab[index].wdata[word] = (tab[index].wdata[word] & mask) | (value & ~mask); // second 32 bits word value = (data_t) (data >> 32); mask = be_to_mask(tab[index].wdata_be[word + 1]); tab[index].wdata[word + 1] = (tab[index].wdata[word + 1] & mask) | (value & ~mask); } ///////////////////////////////////////////////////////////////////// // The erase() function erases an entry in the transaction tab. // Arguments : // - index : the index of the request in the transaction tab ///////////////////////////////////////////////////////////////////// void erase(const size_t index) { assert( (index < size_tab) and "MEMC ERROR: The selected entry is out of range in TRT erase()"); tab[index].valid = false; tab[index].rerror = false; } ///////////////////////////////////////////////////////////////////// // The is_config() function returns the config flag value. // Arguments : // - index : the index of the entry in the transaction tab ///////////////////////////////////////////////////////////////////// bool is_config(const size_t index) { assert( (index < size_tab) and "MEMC ERROR: The selected entry is out of range in TRT is_config()"); return tab[index].config; } }; // end class TransactionTab #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