Lines Matching +full:- +full:set
5 * See the COPYING file in the top-level directory.
12 #include <qemu-plugin.h>
37 * A CacheSet is a set of cache blocks. A memory block that maps to a set can be
38 * put in any of the blocks inside the set. The number of block per set is
45 * In order to search for memory data in the cache, the set identifier and tag
46 * are extracted from the address and the set is probed to see whether a tag
50 * the set number, and the tag.
52 * The set number is used to identify the set in which the block may exist.
53 * The tag is compared against all the tags of a set to search for a match. If a
92 void (*update_hit)(Cache *cache, int set, int blk);
93 void (*update_miss)(Cache *cache, int set, int blk);
118 g_assert((num & (num - 1)) == 0); in pow_of_two()
127 * LRU evection policy: For each set, a generation counter is maintained
130 * On each set access, the generation counter is incremented.
132 * On a cache hit: The hit-block is assigned the current generation counter,
136 * with the newly-cached block, of which the priority is set to the current
144 for (i = 0; i < cache->num_sets; i++) { in lru_priorities_init()
145 cache->sets[i].lru_priorities = g_new0(uint64_t, cache->assoc); in lru_priorities_init()
146 cache->sets[i].lru_gen_counter = 0; in lru_priorities_init()
152 CacheSet *set = &cache->sets[set_idx]; in lru_update_blk() local
153 set->lru_priorities[blk_idx] = cache->sets[set_idx].lru_gen_counter; in lru_update_blk()
154 set->lru_gen_counter++; in lru_update_blk()
161 min_priority = cache->sets[set_idx].lru_priorities[0]; in lru_get_lru_block()
164 for (i = 1; i < cache->assoc; i++) { in lru_get_lru_block()
165 if (cache->sets[set_idx].lru_priorities[i] < min_priority) { in lru_get_lru_block()
166 min_priority = cache->sets[set_idx].lru_priorities[i]; in lru_get_lru_block()
177 for (i = 0; i < cache->num_sets; i++) { in lru_priorities_destroy()
178 g_free(cache->sets[i].lru_priorities); in lru_priorities_destroy()
189 * On a conflict miss: The first-in block is removed from the cache and the new
197 for (i = 0; i < cache->num_sets; i++) { in fifo_init()
198 cache->sets[i].fifo_queue = g_queue_new(); in fifo_init()
202 static int fifo_get_first_block(Cache *cache, int set) in fifo_get_first_block() argument
204 GQueue *q = cache->sets[set].fifo_queue; in fifo_get_first_block()
208 static void fifo_update_on_miss(Cache *cache, int set, int blk_idx) in fifo_update_on_miss() argument
210 GQueue *q = cache->sets[set].fifo_queue; in fifo_update_on_miss()
218 for (i = 0; i < cache->num_sets; i++) { in fifo_destroy()
219 g_queue_free(cache->sets[i].fifo_queue); in fifo_destroy()
225 return addr & cache->tag_mask; in extract_tag()
230 return (addr & cache->set_mask) >> cache->blksize_shift; in extract_set()
238 return "cache size must be divisible by set size (assoc * block size)"; in cache_config_error()
262 cache->assoc = assoc; in cache_init()
263 cache->cachesize = cachesize; in cache_init()
264 cache->num_sets = cachesize / (blksize * assoc); in cache_init()
265 cache->sets = g_new(CacheSet, cache->num_sets); in cache_init()
266 cache->blksize_shift = pow_of_two(blksize); in cache_init()
267 cache->accesses = 0; in cache_init()
268 cache->misses = 0; in cache_init()
270 for (i = 0; i < cache->num_sets; i++) { in cache_init()
271 cache->sets[i].blocks = g_new0(CacheBlock, assoc); in cache_init()
274 blk_mask = blksize - 1; in cache_init()
275 cache->set_mask = ((cache->num_sets - 1) << cache->blksize_shift); in cache_init()
276 cache->tag_mask = ~(cache->set_mask | blk_mask); in cache_init()
303 static int get_invalid_block(Cache *cache, uint64_t set) in get_invalid_block() argument
307 for (i = 0; i < cache->assoc; i++) { in get_invalid_block()
308 if (!cache->sets[set].blocks[i].valid) { in get_invalid_block()
313 return -1; in get_invalid_block()
316 static int get_replaced_block(Cache *cache, int set) in get_replaced_block() argument
320 return g_rand_int_range(rng, 0, cache->assoc); in get_replaced_block()
322 return lru_get_lru_block(cache, set); in get_replaced_block()
324 return fifo_get_first_block(cache, set); in get_replaced_block()
333 uint64_t tag, set; in in_cache() local
336 set = extract_set(cache, addr); in in_cache()
338 for (i = 0; i < cache->assoc; i++) { in in_cache()
339 if (cache->sets[set].blocks[i].tag == tag && in in_cache()
340 cache->sets[set].blocks[i].valid) { in in_cache()
345 return -1; in in_cache()
359 uint64_t tag, set; in access_cache() local
362 set = extract_set(cache, addr); in access_cache()
365 if (hit_blk != -1) { in access_cache()
367 update_hit(cache, set, hit_blk); in access_cache()
372 replaced_blk = get_invalid_block(cache, set); in access_cache()
374 if (replaced_blk == -1) { in access_cache()
375 replaced_blk = get_replaced_block(cache, set); in access_cache()
379 update_miss(cache, set, replaced_blk); in access_cache()
382 cache->sets[set].blocks[replaced_blk].tag = tag; in access_cache()
383 cache->sets[set].blocks[replaced_blk].valid = true; in access_cache()
409 __atomic_fetch_add(&insn->l1_dmisses, 1, __ATOMIC_SEQ_CST); in vcpu_mem_access()
410 l1_dcaches[cache_idx]->misses++; in vcpu_mem_access()
412 l1_dcaches[cache_idx]->accesses++; in vcpu_mem_access()
423 __atomic_fetch_add(&insn->l2_misses, 1, __ATOMIC_SEQ_CST); in vcpu_mem_access()
424 l2_ucaches[cache_idx]->misses++; in vcpu_mem_access()
426 l2_ucaches[cache_idx]->accesses++; in vcpu_mem_access()
437 insn_addr = ((InsnData *) userdata)->addr; in vcpu_insn_exec()
444 __atomic_fetch_add(&insn->l1_imisses, 1, __ATOMIC_SEQ_CST); in vcpu_insn_exec()
445 l1_icaches[cache_idx]->misses++; in vcpu_insn_exec()
447 l1_icaches[cache_idx]->accesses++; in vcpu_insn_exec()
458 __atomic_fetch_add(&insn->l2_misses, 1, __ATOMIC_SEQ_CST); in vcpu_insn_exec()
459 l2_ucaches[cache_idx]->misses++; in vcpu_insn_exec()
461 l2_ucaches[cache_idx]->accesses++; in vcpu_insn_exec()
486 data->disas_str = qemu_plugin_insn_disas(insn); in vcpu_tb_trans()
487 data->symbol = qemu_plugin_insn_symbol(insn); in vcpu_tb_trans()
488 data->addr = effective_addr; in vcpu_tb_trans()
489 g_hash_table_insert(miss_ht, &data->addr, data); in vcpu_tb_trans()
505 g_free(insn->disas_str); in insn_free()
511 for (int i = 0; i < cache->num_sets; i++) { in cache_free()
512 g_free(cache->sets[i].blocks); in cache_free()
519 g_free(cache->sets); in cache_free()
540 g_string_append_printf(line, "%-14" PRIu64 " %-12" PRIu64 " %9.4lf%%" in append_stats_line()
541 " %-14" PRIu64 " %-12" PRIu64 " %9.4lf%%", in append_stats_line()
552 " %-12" PRIu64 " %-11" PRIu64 " %10.4lf%%", in append_stats_line()
567 l1_imisses += l1_icaches[i]->misses; in sum_stats()
568 l1_dmisses += l1_dcaches[i]->misses; in sum_stats()
569 l1_imem_accesses += l1_icaches[i]->accesses; in sum_stats()
570 l1_dmem_accesses += l1_dcaches[i]->accesses; in sum_stats()
573 l2_misses += l2_ucaches[i]->misses; in sum_stats()
574 l2_mem_accesses += l2_ucaches[i]->accesses; in sum_stats()
584 return insn_a->l1_dmisses < insn_b->l1_dmisses ? 1 : -1; in dcmp()
592 return insn_a->l1_imisses < insn_b->l1_imisses ? 1 : -1; in icmp()
600 return insn_a->l2_misses < insn_b->l2_misses ? 1 : -1; in l2_cmp()
619 g_string_append_printf(rep, "%-8d", i); in log_stats()
623 append_stats_line(rep, dcache->accesses, dcache->misses, in log_stats()
624 icache->accesses, icache->misses, in log_stats()
625 l2_cache ? l2_cache->accesses : 0, in log_stats()
626 l2_cache ? l2_cache->misses : 0); in log_stats()
631 g_string_append_printf(rep, "%-8s", "sum"); in log_stats()
638 qemu_plugin_outs(rep->str); in log_stats()
652 for (curr = miss_insns, i = 0; curr && i < limit; i++, curr = curr->next) { in log_top_insns()
653 insn = (InsnData *) curr->data; in log_top_insns()
654 g_string_append_printf(rep, "0x%" PRIx64, insn->addr); in log_top_insns()
655 if (insn->symbol) { in log_top_insns()
656 g_string_append_printf(rep, " (%s)", insn->symbol); in log_top_insns()
659 insn->l1_dmisses, insn->disas_str); in log_top_insns()
665 for (curr = miss_insns, i = 0; curr && i < limit; i++, curr = curr->next) { in log_top_insns()
666 insn = (InsnData *) curr->data; in log_top_insns()
667 g_string_append_printf(rep, "0x%" PRIx64, insn->addr); in log_top_insns()
668 if (insn->symbol) { in log_top_insns()
669 g_string_append_printf(rep, " (%s)", insn->symbol); in log_top_insns()
672 insn->l1_imisses, insn->disas_str); in log_top_insns()
682 for (curr = miss_insns, i = 0; curr && i < limit; i++, curr = curr->next) { in log_top_insns()
683 insn = (InsnData *) curr->data; in log_top_insns()
684 g_string_append_printf(rep, "0x%" PRIx64, insn->addr); in log_top_insns()
685 if (insn->symbol) { in log_top_insns()
686 g_string_append_printf(rep, " (%s)", insn->symbol); in log_top_insns()
689 insn->l2_misses, insn->disas_str); in log_top_insns()
693 qemu_plugin_outs(rep->str); in log_top_insns()
748 sys = info->system_emulation; in qemu_plugin_install()
764 cores = sys ? info->system.smp_vcpus : 1; in qemu_plugin_install()
798 return -1; in qemu_plugin_install()
809 return -1; in qemu_plugin_install()
813 return -1; in qemu_plugin_install()
824 return -1; in qemu_plugin_install()
832 return -1; in qemu_plugin_install()
840 return -1; in qemu_plugin_install()