#line 7719 "smat.w" #line 9165 "smat.w" template struct smat_numeric { enum { log2 = 1 + smat_numeric::log2, on_bit = (n & 1) + smat_numeric::on_bit, is_power_of_two = (on_bit == 1) }; }; template <> struct smat_numeric<2> { enum { log2 = 1, on_bit = 1, is_power_of_two = true }; }; template <> struct smat_numeric<1> { enum { log2 = 0, on_bit = 1, is_power_of_two = true }; }; template <> struct smat_numeric<0> { enum { on_bit = 0, is_power_of_two = false }; }; #line 7719 "smat.w" #line 8118 "smat.w" struct smat_plot { int atime; unsigned addr; size_t size; bool hit, wr; smat_plot() : atime(0), addr(0), size(0), hit(false), wr(false) {} std::ostream& write_readable(std::ostream& os = std::cout) const { static char buf[80]; if (hit) sprintf(buf, "%u %u.0 ? %u\n", atime, addr + size / 2, size / 2); else sprintf(buf, "%u ? %u.0 %u\n", atime, addr + size / 2, size / 2); os << buf; return os; } static std::ostream& write_binary(const int& t, const unsigned &a, const size_t& s, const bool& h, const bool& w, std::ostream& os = std::cout) { unsigned v[3]; v[0] = htonl(t); v[1] = htonl(a); v[2] = htonl((w ? 0x40000000 : 0) | (h ? 0x80000000U : 0) | s & 0x3fffffff); return os.write(reinterpret_cast(v), sizeof(v)); } static std::istream& read_binary(int& t, unsigned &a, size_t& s, bool& h, bool&w, std::istream& is = std::cin) { unsigned v[3], v2; is.read(reinterpret_cast(v), sizeof(v)); t = ntohl(v[0]); a = ntohl(v[1]); v2 = ntohl(v[2]); s = (v2 & 0x3fffffff); h = ((v2 & 0x80000000U) != 0); w = ((v2 & 0x40000000) != 0); return is; } }; inline std::istream& operator>>(std::istream& is, smat_plot& p) { return smat_plot::read_binary(p.atime, p.addr, p.size, p.hit, p.wr, is); } inline std::ostream& operator<<(std::ostream& os, const smat_plot& p) { return p.write_binary(p.atime, p.addr, p.size, p.hit, p.wr, os); } #line 7720 "smat.w" #line 7774 "smat.w" template struct smat_block { Addr tag; bool dirty; Time last_referred; smat_block(Addr t = 0) : tag(t), dirty(false), last_referred(0) {} }; #line 7721 "smat.w" #line 7796 "smat.w" template class smat_set { std::vector > lru; typedef typename std::vector >::iterator iterator; bool is_empty() { for (iterator i = begin(); i != end(); ++i) { if ((*i).tag != 0 || (*i).last_referred != 0) return false; } return true; } public: smat_set() : lru(Assoc) {} iterator begin() { return lru.begin(); } iterator end() { return lru.end(); } iterator find_tag(unsigned int tag) { for (iterator i = begin(); i != end(); ++i) { if ((*i).tag == tag) return i; } return end(); } iterator oldest() { iterator i, o; for (i = o = begin(); i != end(); ++i) { if ((*i).last_referred < (*o).last_referred) o = i; } return o; } void dump(int index, int index_exp, int blocksize_exp, const char *tab) { char buf[80]; if (is_empty()) return; iterator o = oldest(); for (iterator i = begin(); i != end(); ++i) { if ((*i).tag != 0 || (*i).last_referred != 0) { Addr addr = (((*i).tag << (index_exp + blocksize_exp)) | (index << blocksize_exp)); sprintf(buf, "%s%c%08x-%02x:%d:%d%s\n", tab, ((*i).dirty ? '*' : ' '), addr, ((addr + (1 << blocksize_exp) - 1) & 0xff), index, (*i).last_referred, (i == o ? " <--" : " ")); std::cout << buf; } } } }; #line 7722 "smat.w" #line 7730 "smat.w" template class smat_cache { typedef unsigned time_type; typedef unsigned addr_type; typedef smat_set set_type; typedef typename set_type::iterator iterator_type; BOOST_STATIC_ASSERT(smat_numeric::is_power_of_two); BOOST_STATIC_ASSERT(smat_numeric::is_power_of_two); BOOST_STATIC_ASSERT(smat_numeric::is_power_of_two); static const int capacity_exp = smat_numeric::log2; static const int blocksize_exp = smat_numeric::log2; static const int nway_exp = smat_numeric::log2; static const int index_exp = capacity_exp - blocksize_exp - nway_exp; static const int nset = (1 << index_exp); static const addr_type offset_mask = Blocksize - 1; static const addr_type index_mask = (1 << index_exp) - 1; static const addr_type tag_mask = (1 << (32 - blocksize_exp - index_exp)) - 1; Lower lower; std::vector setv; size_t total_read, total_write, hit_, miss_, wb_, wmiss_, whit_; time_type time_; #line 7878 "smat.w" void access(addr_type addr, size_t size, char op) { addr_type next_block_top = (addr + Blocksize) & ~offset_mask; while (next_block_top - addr < size) { access_nosplit(addr, next_block_top - addr, op); size -= (next_block_top - addr); addr = next_block_top; next_block_top += Blocksize; } access_nosplit(addr, size, op); } time_type access_nosplit(addr_type addr, size_t size, char op) { const addr_type index = (addr >> blocksize_exp) & index_mask; const addr_type tag = (addr >> (blocksize_exp + index_exp)) & tag_mask; set_type& s = setv[index]; iterator_type i = s.find_tag(tag); // Block boundary check. The first byte and the last byte of ADDR // must be in the same block. //assert((addr & ~offset_mask) == ((addr + size - 1) & ~offset_mask)); if (op == 'w') total_write += size; else total_read += size; if (Plot) { smat_plot::write_binary(time_, addr, size, (i != s.end()), (op == 'w'), (smat_singleton::ref().fout())); } if (i != s.end()) { // Hit. ++hit_; if (op == 'w') { ++whit_; if (! Writeback) time_ = lower.write_nosplit(addr, size, time_); (*i).dirty = true; } time_ += Hittime; (*i).last_referred = time_; return time_; } ++miss_; i = s.oldest(); if (Writeback && (*i).dirty) { addr_type block_top = (((*i).tag << (index_exp + blocksize_exp)) | (index << blocksize_exp)); time_ = lower.write_nosplit(block_top, Blocksize, time_); ++wb_; } // Fill the cache line. if (op == 'w') { ++wmiss_; //if (size < Blocksize) time_ = lower.read_nosplit(addr & ~offset_mask, Blocksize, time_); if (! Writeback) time_ = lower.write_nosplit(addr & ~offset_mask, Blocksize, time_); } else time_ = lower.read_nosplit(addr & ~offset_mask, Blocksize, time_); time_ += Hittime; (*i).tag = tag; (*i).dirty = (op == 'w' ? true : false); (*i).last_referred = time_; return time_; } #line 7756 "smat.w" public: smat_cache() : setv(nset), total_read(0), total_write(0), hit_(0), miss_(0), wb_(0), wmiss_(0), whit_(0), time_(0) {} #line 7996 "smat.w" void dtor(addr_type addr, size_t size) { if ((addr & offset_mask) == 0 && size == Blocksize) { const unsigned index = (addr >> blocksize_exp) & index_mask; set_type& s = setv[index]; const unsigned tag = (addr >> (blocksize_exp + index_exp)) & tag_mask; iterator_type i = s.find_tag(tag); if (i != s.end()) { (*i).last_referred = 0; (*i).dirty = false; } } else if (size < Blocksize) return; else { addr_type next_block_top = (addr + Blocksize) & ~offset_mask; while (next_block_top - addr < size) { dtor(addr, next_block_top - addr); size -= (next_block_top - addr); addr = next_block_top; next_block_top += Blocksize; } dtor(addr, next_block_top - addr); } } #line 7761 "smat.w" #line 8035 "smat.w" size_t hit(const char id) { return id == Id ? hit_ : lower.hit(id); } size_t miss(const char id) { return id == Id ? miss_ : lower.miss(id); } size_t whit(const char id) { return id == Id ? whit_ : lower.whit(id); } size_t wmiss(const char id) { return id == Id ? wmiss_ : lower.wmiss(id); } size_t wb(const char id) { return id == Id ? wb_ : lower.wb(id); } size_t r(const char id) { return id == Id ? total_read : lower.r(id); } size_t w(const char id) { return id == Id ? total_write : lower.w(id); } time_type time(const char id) { return id == Id ? time_ : lower.time(id); } #line 7762 "smat.w" #line 7970 "smat.w" time_type read_nosplit(addr_type addr, size_t size, time_type current_time) { time_ = current_time; return access_nosplit(addr, size, 'r'); } time_type write_nosplit(addr_type addr, size_t size, time_type current_time) { time_ = current_time; return access_nosplit(addr, size, 'w'); } void read(addr_type addr, size_t size) { access(addr, size, 'r'); } void write(addr_type addr, size_t size) { access(addr, size, 'w'); } #line 7763 "smat.w" #line 8099 "smat.w" void dump() { int i = 0; for (typename std::vector::iterator vi = setv.begin(); vi != setv.end(); ++vi, ++i) (*vi).dump(i, index_exp, blocksize_exp, "\t "); std::cout << '\n'; lower.dump(); } #line 7764 "smat.w" }; #line 7723 "smat.w" #line 8065 "smat.w" template class smat_cache_main { size_t total_read, total_write; public: smat_cache_main() : total_read(0), total_write(0) {} size_t hit(const char) { return 0; } size_t miss(const char) { return 0; } size_t whit(const char) { return 0; } size_t wmiss(const char) { return 0; } size_t wb(const char) { return 0; } size_t r(const char) { return total_read; } size_t w(const char) { return total_write; } unsigned time(const char) { return 0; } unsigned read_nosplit(unsigned, size_t size, unsigned current_time) { total_read += size; return current_time + Hittime; } unsigned write_nosplit(unsigned, size_t size, unsigned current_time) { total_write += size; return current_time + Hittime; } void dump() { } }; #line 7724 "smat.w"