void moesi_handler_find_and_lock(int event, void *data) { struct moesi_stack_t *stack = data, *ret = stack->retstack, *newstack; struct ccache_t *ccache = stack->ccache; if (event == EV_MOESI_FIND_AND_LOCK) { int hit; cache_debug(" %lld %lld 0x%x %s find and lock (blocking=%d)\n", CYCLE, ID, stack->addr, ccache->name, stack->blocking); /* Default return values */ ret->err = 0; ret->set = 0; ret->way = 0; ret->status = 0; ret->tag = 0; /* Look for block. */ hit = ccache_find_block(ccache, stack->addr, &stack->set, &stack->way, &stack->tag, &stack->status); if (hit) cache_debug(" %lld 0x%x %s hit: set=%d, way=%d, status=%d\n", ID, stack->tag, ccache->name, stack->set, stack->way, stack->status); /* Stats */ ccache->accesses++; if (hit) ccache->hits++; if (stack->read) { ccache->reads++; stack->blocking ? ccache->blocking_reads++ : ccache->non_blocking_reads++; if (hit) ccache->read_hits++; } else { ccache->writes++; stack->blocking ? ccache->blocking_writes++ : ccache->non_blocking_writes++; if (hit) ccache->write_hits++; } if (!stack->retry) { ccache->no_retry_accesses++; if (hit) ccache->no_retry_hits++; if (stack->read) { ccache->no_retry_reads++; if (hit) ccache->no_retry_read_hits++; } else { ccache->no_retry_writes++; if (hit) ccache->no_retry_write_hits++; } } /* Miss */ if (!hit) { assert(!stack->blocking); assert(ccache != main_memory); /* Find victim */ stack->way = cache_replace_block(ccache->cache, stack->set); cache_get_block(ccache->cache, stack->set, stack->way, NULL, &stack->status); assert(stack->status || !dir_entry_group_shared_or_owned(ccache->dir, stack->set, stack->way)); cache_debug(" %lld 0x%x %s miss -> lru: set=%d, way=%d, status=%d\n", ID, stack->tag, ccache->name, stack->set, stack->way, stack->status); } /* Lock entry */ stack->dir_lock = ccache_get_dir_lock(ccache, stack->set, stack->way); if (stack->dir_lock->lock && !stack->blocking) { cache_debug(" %lld 0x%x %s block already locked: set=%d, way=%d\n", ID, stack->tag, ccache->name, stack->set, stack->way); ret->err = 1; moesi_stack_return(stack); return; } if (!dir_lock_lock(stack->dir_lock, EV_MOESI_FIND_AND_LOCK, stack)) return; /* Entry is locked. Record the transient tag so that a subsequent lookup * detects that the block is being brought. */ if (ccache->cache) cache_set_transient_tag(ccache->cache, stack->set, stack->way, stack->tag); /* On miss, evict if victim is a valid block. */ if (!hit && stack->status) { stack->eviction = 1; newstack = moesi_stack_create(stack->id, ccache, 0, EV_MOESI_FIND_AND_LOCK_FINISH, stack); newstack->set = stack->set; newstack->way = stack->way; esim_schedule_event(EV_MOESI_EVICT, newstack, ccache->lat); return; } /* Access latency */ esim_schedule_event(EV_MOESI_FIND_AND_LOCK_FINISH, stack, ccache->lat); return; } if (event == EV_MOESI_FIND_AND_LOCK_FINISH) { cache_debug(" %lld %lld 0x%x %s find and lock finish (err=%d)\n", CYCLE, ID, stack->tag, ccache->name, stack->err); /* If evict produced err, return err */ if (stack->err) { cache_get_block(ccache->cache, stack->set, stack->way, NULL, &stack->status); assert(stack->status); assert(stack->eviction); ret->err = 1; dir_lock_unlock(stack->dir_lock); moesi_stack_return(stack); return; } /* Eviction */ if (stack->eviction) { ccache->evictions++; cache_get_block(ccache->cache, stack->set, stack->way, NULL, &stack->status); assert(!stack->status); } /* Return */ ret->err = 0; ret->set = stack->set; ret->way = stack->way; ret->status = stack->status; ret->tag = stack->tag; ret->dir_lock = stack->dir_lock; moesi_stack_return(stack); return; } abort(); }
/* Event handler for EV_MEM_SYSTEM_END_COMMAND. * The event data is a string of type 'char *' that needs to be deallocated * after processing this event. */ void mem_system_end_command_handler(int event, void *data) { char *command_line = data; char command[MAX_STRING_SIZE]; char msg[MAX_STRING_SIZE]; char msg_detail[MAX_STRING_SIZE]; char *msg_str = msg; int msg_size = sizeof msg; char *msg_detail_str = msg_detail; int msg_detail_size = sizeof msg_detail; int test_failed; struct list_t *token_list; /* Split command in tokens, skip command */ token_list = str_token_list_create(command_line, " "); assert(list_count(token_list)); /* Get command */ mem_system_command_get_string(token_list, command_line, command, sizeof command); /* Messages */ test_failed = 0; *msg_str = '\0'; *msg_detail_str = '\0'; /* Command 'SetBlock' */ if (!strcasecmp(command, "CheckBlock")) { struct mod_t *mod; int set; int way; int tag; int tag_check; int state; int state_check; mod = mem_system_command_get_mod(token_list, command_line); mem_system_command_get_set_way(token_list, command_line, mod, &set, &way); tag = mem_system_command_get_hex(token_list, command_line); state = mem_system_command_get_state(token_list, command_line); mem_system_command_end(token_list, command_line); /* Check that module serves address */ if (!mod_serves_address(mod, tag)) fatal("%s: %s: module does not serve address 0x%x.\n\t> %s", __FUNCTION__, mod->name, tag, command_line); /* Output */ str_printf(&msg_str, &msg_size, "check module %s, set %d, way %d - state %s, tag 0x%x", mod->name, set, way, str_map_value(&cache_block_state_map, state), tag); /* Check */ cache_get_block(mod->cache, set, way, &tag_check, &state_check); if (tag != tag_check) { test_failed = 1; str_printf(&msg_detail_str, &msg_detail_size, "\ttag 0x%x found, but 0x%x expected\n", tag_check, tag); } if (state != state_check) { test_failed = 1; str_printf(&msg_detail_str, &msg_detail_size, "\tstate %s found, but %s expected\n", str_map_value(&cache_block_state_map, state_check), str_map_value(&cache_block_state_map, state)); } } /* Command 'CheckOwner' */ else if (!strcasecmp(command, "CheckOwner")) { struct mod_t *mod; struct mod_t *owner; struct mod_t *owner_check = NULL; struct net_node_t *net_node; struct dir_entry_t *dir_entry; int set; int way; int sub_block; /* Read fields */ mod = mem_system_command_get_mod(token_list, command_line); mem_system_command_get_set_way(token_list, command_line, mod, &set, &way); sub_block = mem_system_command_get_sub_block(token_list, command_line, mod, set, way); owner = mem_system_command_get_mod(token_list, command_line); mem_system_command_end(token_list, command_line); /* Get actual owner */ owner_check = NULL; if (mod->dir) { dir_entry = dir_entry_get(mod->dir, set, way, sub_block); if (dir_entry->owner >= 0) { assert(mod->high_net); net_node = list_get(mod->high_net->node_list, dir_entry->owner); owner_check = net_node->user_data; } } /* Message */ str_printf(&msg_str, &msg_size, "check owner at module %s, set %d, way %d, subblock %d - %s", mod->name, set, way, sub_block, owner ? owner->name : "None"); /* Check match */ if (owner != owner_check) { test_failed = 1; str_printf(&msg_detail_str, &msg_detail_size, "\towner %s found, but %s expected\n", owner_check ? owner_check->name : "None", owner ? owner->name : "None"); } } /* Command 'CheckSharers' */ else if (!strcasecmp(command, "CheckSharers")) { struct mod_t *mod; struct mod_t *sharer; struct net_node_t *node; int set; int way; int sub_block; int node_index; struct linked_list_t *sharers_list; struct linked_list_t *sharers_check_list; /* Read fields */ mod = mem_system_command_get_mod(token_list, command_line); mem_system_command_get_set_way(token_list, command_line, mod, &set, &way); sub_block = mem_system_command_get_sub_block(token_list, command_line, mod, set, way); mem_system_command_expect(token_list, command_line); /* Construct list of expected sharers */ sharers_list = linked_list_create(); while (list_count(token_list)) { sharer = mem_system_command_get_mod(token_list, command_line); linked_list_add(sharers_list, sharer); } /* Output */ str_printf(&msg_str, &msg_size, "check sharers at module %s, set %d, way %d, subblock %d - { ", mod->name, set, way, sub_block); LINKED_LIST_FOR_EACH(sharers_list) { sharer = linked_list_get(sharers_list); if (sharer) str_printf(&msg_str, &msg_size, "%s ", sharer->name); } str_printf(&msg_str, &msg_size, "}"); /* Construct list of actual sharers */ sharers_check_list = linked_list_create(); assert(mod->high_net); for (node_index = 0; node_index < mod->high_net->node_count; node_index++) { if (!dir_entry_is_sharer(mod->dir, set, way, sub_block, node_index)) continue; node = list_get(mod->high_net->node_list, node_index); sharer = node->user_data; linked_list_add(sharers_check_list, sharer); } /* Remove in actual sharers everything from expected sharers */ LINKED_LIST_FOR_EACH(sharers_list) { /* Get expected sharer */ sharer = linked_list_get(sharers_list); if (!sharer) continue; /* Check that it's an actual sharer */ linked_list_find(sharers_check_list, sharer); if (sharers_check_list->error_code) { test_failed = 1; str_printf(&msg_detail_str, &msg_detail_size, "\tsharer %s expected, but not found\n", sharer->name); } /* Remove from actual sharers */ linked_list_remove(sharers_check_list); } /* Check that there is no actual sharer left */ LINKED_LIST_FOR_EACH(sharers_check_list) { sharer = linked_list_get(sharers_check_list); test_failed = 1; str_printf(&msg_detail_str, &msg_detail_size, "\tsharer %s found, but not expected\n", sharer->name); } /* Free lists */ linked_list_free(sharers_list); linked_list_free(sharers_check_list); } /* Command 'CheckLink' */ else if (!strcasecmp(command, "CheckLink"))
void estadisticas_por_intervalos(long long intervalo){ //double latencia; int z, x, y, k, i; //long long ipc; if((intervalo_anterior + ventana_muestreo) > intervalo ) return; long long latency = mem_stats.load_latency - ciclos_mem_stats_anterior.load_latency; long long contador = mem_stats.load_latency_count - ciclos_mem_stats_anterior.load_latency_count; /* // mshr mem_stats.superintervalo_latencia += latency; mem_stats.superintervalo_contador += contador; mem_stats.superintervalo_operacion += gpu_stats.total - instrucciones_gpu_stats_anterior.total; mem_stats.superintervalo_ciclos += cycle - ipc_last_cycle; if(mshr_control_enabled && !(gpu_stats.total % 500000)) { mshr_control(mem_stats.superintervalo_contador ? mem_stats.superintervalo_latencia/mem_stats.superintervalo_contador : 0, mem_stats.superintervalo_operacion/mem_stats.superintervalo_ciclos); mem_stats.superintervalo_latencia = 0; mem_stats.superintervalo_contador = 0; mem_stats.superintervalo_operacion = 0; mem_stats.superintervalo_ciclos = 0; } */ fran_debug_general("%lld %lld ",latency, contador); fran_debug_general("%lld ",mem_stats.mod_level[0].coalesce - ciclos_mem_stats_anterior.mod_level[0].coalesce); fran_debug_general("%lld ",mem_stats.mod_level[0].accesses - ciclos_mem_stats_anterior.mod_level[0].accesses); fran_debug_general("%lld ",mem_stats.mod_level[1].coalesce - ciclos_mem_stats_anterior.mod_level[1].coalesce); fran_debug_general("%lld ",mem_stats.mod_level[1].accesses - ciclos_mem_stats_anterior.mod_level[1].accesses); fran_debug_general("%lld ",mem_stats.mod_level[1].hits - ciclos_mem_stats_anterior.mod_level[1].hits); fran_debug_general("%lld ",mem_stats.mod_level[1].invalidations - ciclos_mem_stats_anterior.mod_level[1].invalidations); fran_debug_general("%lld ",mem_stats.mod_level[2].coalesce - ciclos_mem_stats_anterior.mod_level[2].coalesce); fran_debug_general("%lld ",mem_stats.mod_level[2].accesses - ciclos_mem_stats_anterior.mod_level[2].accesses); fran_debug_general("%lld ",mem_stats.mod_level[2].hits - ciclos_mem_stats_anterior.mod_level[2].hits); fran_debug_general("%lld ",mem_stats.mod_level[2].invalidations - ciclos_mem_stats_anterior.mod_level[2].invalidations); fran_debug_general("%lld ",mem_stats.mod_level[1].busy_cicles_in - ciclos_mem_stats_anterior.mod_level[1].busy_cicles_in); fran_debug_general("%lld ",mem_stats.mod_level[1].busy_cicles_out - ciclos_mem_stats_anterior.mod_level[1].busy_cicles_out); fran_debug_general("%lld ",mem_stats.mod_level[2].busy_cicles_in - ciclos_mem_stats_anterior.mod_level[2].busy_cicles_in); fran_debug_general("%lld ",mem_stats.mod_level[2].busy_cicles_out - ciclos_mem_stats_anterior.mod_level[2].busy_cicles_out); fran_debug_general("%lld ",mem_stats.mod_level[1].latencia_red_acc - ciclos_mem_stats_anterior.mod_level[1].latencia_red_acc); fran_debug_general("%lld ",mem_stats.mod_level[1].latencia_red_cont - ciclos_mem_stats_anterior.mod_level[1].latencia_red_cont); fran_debug_general("%lld ",mem_stats.mod_level[2].latencia_red_acc - ciclos_mem_stats_anterior.mod_level[2].latencia_red_acc); fran_debug_general("%lld ",mem_stats.mod_level[2].latencia_red_cont - ciclos_mem_stats_anterior.mod_level[2].latencia_red_cont); memcpy(&ciclos_mem_stats_anterior,&mem_stats,sizeof(struct mem_system_stats)); int tag_ptr; int state_ptr; contador = 0; long long locked[5] = {0,0,0,0,0}; struct mod_t *mod; struct cache_t *cache; struct dir_t *dir; long long replica = 0; long long compartido = 0; for (k = 0; k < list_count(mem_system->mod_list); k++) { mod = list_get(mem_system->mod_list, k); dir = mod->dir; cache = mod->cache; for (x = 0; x < dir->xsize; x++) { for (y = 0; y < dir->ysize; y++) { struct dir_lock_t *dir_lock = &dir->dir_lock[x * dir->ysize + y]; if(dir_lock->lock) locked[mod->level]++; if(mod->level != 2) continue; cache_get_block(cache, x, y, &tag_ptr, &state_ptr); if(state_ptr) { for (z = 0; z < dir->zsize; z++) { contador = 0; for (i = 0; i < dir->num_nodes; i++) { if (dir_entry_is_sharer(dir, x, y, z, i)) { contador++; if(contador == 1) { compartido++; } else { replica++; } } } } } } } } fran_debug_general("%lld ",compartido); fran_debug_general("%lld ",replica); fran_debug_general("%lld ",locked[1]); fran_debug_general("%lld ",locked[2]); fran_debug_general("%lld %lld\n",intervalo - intervalo_anterior , intervalo); intervalo_anterior = intervalo; }