void Cache :: line_evict(Line *line) { NVLOG1("%s\tline_evict addr 0x%lx data 0x%lx\n", this->_name.c_str(), line->addr, (Addr)line->pdata); // evict in all child caches for (size_t child_i = 0; child_i<_children.size() && line->sharers>0; child_i++) { if (!bit(line->sharers, child_i)) continue; // a child is not a sharer, so continue Cache *child = dynamic_cast<Cache *>(_children[child_i]); assert(child!=NULL); for (Addr line_addr_iter=line->addr; line_addr_iter<line->addr+get_line_size(); line_addr_iter += child->get_line_size()) { Line *child_line = child->addr2line_internal(line_addr_iter); if (child_line == NULL) continue; child->line_evict(child_line); } } #ifdef HAS_HTM if (pprocessor) { pprocessor->cb_line_evicted(line); } #endif if (!_parent_cache) { // notify the processor of the line removal #ifdef HAS_HTM assert(pprocessor); pprocessor->cb_line_evicted(line); #endif } this->line_data_writeback(line); // check if there is any data to writeback free(line->pdata); line->pdata = NULL; // remove in this cache as well this->line_rm(line); }
void Cache :: line_writer_to_sharer(Line *line, size_t &latency, bool children_only) { // make this cache (and child caches) // only sharers of the line (downgrade from a writer) NVLOG1("%s\tline_writer_to_sharer 0x%lx +%ld cycles\n", this->_name.c_str(), line->addr, _hit_latency); latency += _hit_latency; this->stats.writebacks_inc(); for (size_t child_i = 0; child_i<_children.size(); child_i++) { if (!bit(line->sharers, child_i)) continue; // a child is not a sharer, so continue Cache *child = dynamic_cast<Cache *>(_children[child_i]); assert(child!=NULL); for (Addr line_addr_iter=line->addr; line_addr_iter<line->addr+get_line_size(); line_addr_iter += child->get_line_size()) { if (line_addr_iter!=line->addr) { // also measure the latency for other line segments NVLOG1("%s\tline_writer_to_sharer 0x%lx +%ld cycles\n", this->_name.c_str(), line_addr_iter, _hit_latency); latency += _hit_latency; // response from child to parent this->stats.writebacks_inc(); } Line *child_line = child->addr2line_internal(line_addr_iter); if (!child_line) continue; child->line_writer_to_sharer(child_line, latency); } } if (!children_only) { this->line_data_writeback(line); line->state &= ~(LINE_MOD | LINE_EXC); line->state |= LINE_SHR; } NVLOG1("%s\t0x%lx\t new state %s sharers %lx\n", _name.c_str(), line->addr, state2str(line->state).c_str(), line->sharers ); }
void Cache :: line_rm_recursive(Addr addr) { Line *line = addr2line_internal(addr); if (line==NULL) return; NVLOG1("%s\tline_rm_recursive addr 0x%lx\n", this->_name.c_str(), addr); for (size_t child_i = 0; child_i<_children.size() && line->sharers>0; child_i++) { if (!bit(line->sharers, child_i)) continue; // a child is not a sharer, so continue Cache *child = dynamic_cast<Cache *>(_children[child_i]); assert(child!=NULL); for (Addr line_addr_iter=line->addr; line_addr_iter<line->addr+get_line_size(); line_addr_iter += child->get_line_size()) { child->line_rm_recursive(line_addr_iter); } } #ifdef HAS_HTM if (pprocessor) { pprocessor->cb_line_evicted(line); } #endif free(line->pdata); line->pdata = NULL; // remove in this cache as well this->line_rm(line); }
bool Cache :: line_make_owner_in_child_caches(Line *line, unsigned child_index) { NVLOG1("%s\tline_make_owner_in_child_caches 0x%lx sharers %lx caller %d\n", this->_name.c_str(), line->addr, line->sharers, child_index); uint8_t __attribute__((unused)) line_state_orig = line->state; uint64_t __attribute__((unused)) line_sharers_orig = line->sharers; // evict the line in all but the requesting child cache for (size_t child_i = 0; child_i<_children.size() && line->sharers>0; child_i++) { Cache *child = dynamic_cast<Cache *>(_children[child_i]); assert(child!=NULL); // NVLOG1("%s\tchecking for 0x%lx %lx 1\n", child->_name.c_str(), line->addr, line->sharers); if (!bit(line->sharers, child_i)) continue; // a child is not a sharer, so continue // NVLOG1("%s\tchecking for 0x%lx %lx 2\n", child->_name.c_str(), line->addr, line->sharers); if (child_i == child_index) continue; // skip the child cache that called us // NVLOG1("%s\tchecking for 0x%lx %lx 3\n", child->_name.c_str(), line->addr, line->sharers); for (Addr line_addr_iter=line->addr; line_addr_iter<line->addr+get_line_size(); line_addr_iter += child->get_line_size()) { NVLOG1("%s\tis line sharer, checking segment 0x%lx\n", child->_name.c_str(), line_addr_iter); Line *child_line = child->addr2line_internal(line_addr_iter); if (!child_line) continue; NVLOG1("%s\thas segment 0x%lx, evicting\n", child->_name.c_str(), line_addr_iter); child->line_evict(child_line); } } line->sharers = 0; setbit(line->sharers, child_index); NVLOG1("%s\tline 0x%lx\t state %s->%s sharers 0x%lx->0x%lx\n", _name.c_str(), line->addr, state2str(line_state_orig).c_str(), state2str(line->state).c_str(), line_sharers_orig, line->sharers); return true; }