📄 mpcache.c
字号:
SET_L1_STATE (pid, L1_line, MODIFIED); SET_L2_STATE (pid, L2_line, MODIFIED_ABOVE); } break; } } else /* no tag match, _or_ invalid state with tag match */ { /* no tag match in L1, so pure miss */ mpcachestats[pid].L1_misses++;#ifdef GRAPHICS L1_miss_count[pid]++;#endif /* GRAPHICS */ /* determine if writeback of current _L1_ line to L2 is needed */ /* (note that this would not be needed if tag matched with invalid */ if (L1_states[pid][L1_line] == MODIFIED) { /* reconstruct address of line being replaced */ unsigned long L2_wback_addr = (L1_tags[pid][L1_line] << L1_tag_shift) | (L1_line << L1_line_shift); /* determine which line in L2 it belongs in */ unsigned int L2_wback_line = (L2_wback_addr >> L2_line_shift) & L2_line_mask; unsigned int L2_wback_tag = (L2_wback_addr >> L2_tag_shift); /* mark current L1 line (which will be written back to L2) as INVALID to allow 'CheckL1States()' to work properly (note that graphics are not informed of this change) */ L1_states[pid][L1_line] = INVALID; /* check if other modified subblocks of wback L2 line are in L1 */ /* if none, then change state of wback L2 line to just modified */ /* (otherwise, remains modified_above) */ if (CheckL1States (pid, L2_wback_tag, L2_wback_line, MODIFIED)== 0) SET_L2_STATE (pid, L2_wback_line, MODIFIED); /* update count of writebacks to L2 */ mpcachestats[pid].L2_writebacks++; } /* now check if we have the missing data in L2 */ if (L2_tags[pid][L2_line] == L2_tag && L2_states[pid][L2_line] != INVALID) { if (! is_a_store) { mpcachestats[pid].L2_hits++; /* valid tag match for read */ /* this is the easy case; just use same state as L2, except if state is modified or modified_above */ SET_L1_STATE (pid, L1_line, (L2_states[pid][L2_line] == MODIFIED || L2_states[pid][L2_line] == MODIFIED_ABOVE) ? EXCLUSIVE : L2_states[pid][L2_line]); L1_tags[pid][L1_line] = L1_tag; } else /* is_a_store */ { /* set tag in L1 */ L1_tags[pid][L1_line] = L1_tag; /* check if an upgrade request is needed */ if (L2_states[pid][L2_line] == SHARED) { mpcachestats[pid].L2_upgrades++; InvalidateOtherCaches (pid, /* who is invalidating */ L2_tag, L2_line); /* make all other L1 subblocks exclusive except for the one that will change to modified */ UpdateL1StatesExceptOne (pid, L2_tag, L2_line, EXCLUSIVE, L1_line); /* change L1 state to modified */ SET_L1_STATE (pid, L1_line, MODIFIED); /* change L2 state */ SET_L2_STATE (pid, L2_line, MODIFIED_ABOVE); } else /* either exclusive or already modified in L2 */ { mpcachestats[pid].L2_hits++; /* hit */ /* change L1 and L2 states */ SET_L1_STATE (pid, L1_line, MODIFIED); if (L2_states[pid][L2_line] == EXCLUSIVE) mpcachestats[pid].exclusive_to_modified_changes++; SET_L2_STATE (pid, L2_line, MODIFIED_ABOVE); } } } else { /* pure miss in L2 */ mpcachestats[pid].L2_misses++;#ifdef GRAPHICS L2_miss_count[pid]++;#endif /* GRAPHICS */ /* check whether location of missing line in L2 needs mem wback */ if ( L2_states[pid][L2_line] == MODIFIED || L2_states[pid][L2_line] == MODIFIED_ABOVE) { /* mem writeback needed */ mpcachestats[pid].mem_writebacks++; /* we must invalidate _all_ subblocks of this L2 line in L1 */ UpdateL1States (pid, L2_tag, L2_line, INVALID); } /* set tags in L1 and L2 */ L1_tags[pid][L1_line] = L1_tag; L2_tags[pid][L2_line] = L2_tag; /* base on type of mem ref, update statistics for bus requests, update other caches, and finally update states in L1 and L2 */ if (is_a_store) { mpcachestats[pid].read_excl_requests++; (void) CheckAndUpdateL2Copies (pid, L2_tag, L2_line, READ_EX); SET_L1_STATE (pid, L1_line, MODIFIED); SET_L2_STATE (pid, L2_line, MODIFIED_ABOVE); } else /* is a load */ { mpcachestats[pid].read_requests++; /* with snooping, the data response would indicate whether this processor could set its final line state to shared or exclusive */ if (CheckAndUpdateL2Copies (pid, L2_tag, L2_line, READ) > 0) { /* at least one other copy in another cache */ SET_L1_STATE (pid, L1_line, SHARED); SET_L2_STATE (pid, L2_line, SHARED); } else { /* no other copies in any other cache */ SET_L1_STATE (pid, L1_line, EXCLUSIVE); SET_L2_STATE (pid, L2_line, EXCLUSIVE); /* keep track of how many exclusive responses for reads */ mpcachestats[pid].exclusive_data_returns++; } } } }#ifdef GRAPHICS /* update miss ratio bar graph display for this processor */ if (graphics_flag && ++ref_count[pid] == MISS_INTERVAL) { int L1_miss_ratio = (int) (L1_miss_count[pid] / (double) MISS_INTERVAL * 100.0); int L2_miss_ratio = (L1_miss_count[pid] == 0) ? 0 : (int) ((double) L2_miss_count[pid] / L1_miss_count[pid] * 100.0); ref_count[pid] = L1_miss_count[pid] = L2_miss_count[pid] = 0; if (L1_miss_ratio < L1_last_miss_ratio[pid]) ClearWindowArea (P_X + Q_OFFSET (pid, BAR_WIDTH, 1), 100-L1_last_miss_ratio[pid], BAR_WIDTH, (L1_last_miss_ratio[pid] - L1_miss_ratio)); else { SetColor (BLUE); DrawFilledRectangle (P_X + Q_OFFSET (pid, BAR_WIDTH, 1), 100-L1_miss_ratio, BAR_WIDTH, (L1_miss_ratio - L1_last_miss_ratio[pid])); } if (L2_miss_ratio < L2_last_miss_ratio[pid]) ClearWindowArea (P_X + Q_OFFSET (pid, BAR_WIDTH, 2), 100-L2_last_miss_ratio[pid], BAR_WIDTH, (L2_last_miss_ratio[pid] - L2_miss_ratio)); else { SetColor (RED); DrawFilledRectangle (P_X + Q_OFFSET (pid, BAR_WIDTH, 2), 100-L2_miss_ratio, BAR_WIDTH, (L2_miss_ratio - L2_last_miss_ratio[pid])); } L1_last_miss_ratio[pid] = L1_miss_ratio; L2_last_miss_ratio[pid] = L2_miss_ratio; FlushWindow (); } /* finally, make periodic checks of the X event queue for exposures or unmap events in order to refresh or to alter mapped flag (does not necessarily process X events in the order that they appear in the queue, but should be sufficient for normal use) */ if (graphics_flag && ++window_event_interval_count >= WINDOW_EVENT_INTERVAL) { window_event_interval_count = 0; if (ExposureCheck ()) /* any pending exposure events ? */ { ConsumeExposures (); /* if so, consume them all */ ConsumeMapEvents (); /* along with any map events */ RefreshEntireDisplay (); /* then redraw graphics */ if (! mapped) /* we also use exposures to set */ mapped = 1; /* mapped flag if it was unmapped */ } if (UnmapCheck ()) /* any pending unmap events ? */ mapped = 0; /* if so, reset flag */ }#endif /* GRAPHICS */}/*------------------------------------------------------------------*/void MPCacheReport (void){ int i, j, **grid; double **fgrid; unsigned int total_read_requests = 0, total_read_excl_requests = 0, total_mem_writebacks = 0, total_upgrade_requests = 0, total_shared_responses = 0, total_exclusive_responses = 0, total_bus_requests = 0; struct stat_stat_t *stat_ptr; unsigned int *num_instructions; /* retrieve array of instruction counts from statistics database */ stat_ptr = stat_find_stat (sim_sdb, "sim_num_instructions"); if (stat_ptr == NULL) fatal ("unable to retrieve array of instruction counts" "for final report"); /* make pointer to array of counts */ num_instructions = stat_ptr->variant.for_uintarray.var; for (i = 0; i < num_created_processes; i++) { /* compute final statistics */ mpcachestats[i].num_instructions = num_instructions[i]; mpcachestats[i].upgrade_requests = mpcachestats[i].L1_upgrades + mpcachestats[i].L2_upgrades; mpcachestats[i].L1_miss_ratio = (double) mpcachestats[i].L1_misses / mpcachestats[i].L1_accesses * 100.0; mpcachestats[i].L1_upgrade_miss_ratio = (double) mpcachestats[i].L1_upgrades / mpcachestats[i].L1_accesses * 100.0; mpcachestats[i].L2_accesses = mpcachestats[i].L1_misses; mpcachestats[i].L2_miss_ratio = (double) mpcachestats[i].L2_misses / mpcachestats[i].L2_accesses * 100.0; mpcachestats[i].L2_upgrade_miss_ratio = (double) mpcachestats[i].L1_upgrades / mpcachestats[i].L2_accesses * 100.0; mpcachestats[i].snoop_hit_ratio = (double) mpcachestats[i].snoop_hits / mpcachestats[i].external_bus_requests * 100.0; total_read_requests += mpcachestats[i].read_requests; total_read_excl_requests += mpcachestats[i].read_excl_requests; total_mem_writebacks += mpcachestats[i].mem_writebacks; total_upgrade_requests += mpcachestats[i].upgrade_requests; total_shared_responses += mpcachestats[i].shared_data_responses; total_exclusive_responses += mpcachestats[i].exclusive_data_responses; } /* create a integer "grid" and a floating-point "grid" for the final output of statistics (note that both grids are allocated to match the total number of statistics, but only a portion of each one is used; inefficient, but simple) */ grid = (int **) malloc (NUM_STATISTICS * sizeof (int *)); for (j = 0; j < NUM_STATISTICS; j++) grid[j] = (int *) malloc (num_created_processes * sizeof (int)); fgrid = (double **) malloc (NUM_STATISTICS * sizeof (double *)); for (j = 0; j < NUM_STATISTICS; j++) fgrid[j] = (double *) malloc (num_created_processes * sizeof (double)); for (i = 0; i < num_created_processes; i++) /* loop through processors */ { int j = 0; /* counter to step through the "grids" */ grid[j++][i] = mpcachestats[i].num_instructions; grid[j++][i] = mpcachestats[i].L1_accesses; grid[j++][i] = mpcachestats[i].L1_stores; grid[j++][i] = mpcachestats[i].L1_hits; grid[j++][i] = mpcachestats[i].L1_misses; fgrid[j++][i] = mpcachestats[i].L1_miss_ratio; grid[j++][i] = mpcachestats[i].L1_upgrades; fgrid[j++][i] = mpcachestats[i].L1_upgrade_miss_ratio; grid[j++][i] = mpcachestats[i].L2_writebacks; grid[j++][i] = mpcachestats[i].L2_accesses; grid[j++][i] = mpcachestats[i].L2_hits; grid[j++][i] = mpcachestats[i].L2_misses; fgrid[j++][i] = mpcachestats[i].L2_miss_ratio; grid[j++][i] = mpcachestats[i].L2_upgrades; fgrid[j++][i] = mpcachestats[i].L2_upgrade_miss_ratio; grid[j++][i] = mpcachestats[i].mem_writebacks; grid[j++][i] = mpcachestats[i].exclusive_to_modified_changes; grid[j++][i] = mpcachestats[i].read_requests; grid[j++][i] = mpcachestats[i].exclusive_data_returns; grid[j++][i] = mpcachestats[i].read_excl_requests; grid[j++][i] = mpcachestats[i].upgrade_requests; grid[j++][i] = mpcachestats[i].external_bus_requests; grid[j++][i] = mpcachestats[i].snoop_hits; fgrid[j++][i] = mpcachestats[i].snoop_hit_ratio; grid[j++][i] = mpcachestats[i].exclusive_to_shared_changes; grid[j++][i] = mpcachestats[i].shared_data_responses; grid[j++][i] = mpcachestats[i].exclusive_data_responses; grid[j++][i] = mpcachestats[i].external_invalidations; } printf ("\n"); printf ("statistic\t"); for (i = 0; i < num_created_processes; i++) printf ("\tPID %d", i); printf ("\n\n"); for (j = 0; j < NUM_STATISTICS; j++) { printf ("%-23s", stat_names[j]); for (i = 0; i < num_created_processes; i++) if (double_flags[j]) printf ("\t%.2f%%", fgrid[j][i]); else printf ("\t%d", grid[j][i]); printf ("\n"); } for (j = 0; j < NUM_STATISTICS; j++) { free (grid[j]); free (fgrid[j]); } free (grid); free (fgrid); printf ("\n"); printf ("===== Invalidation set size statistics ===== \n"); printf ("\n"); printf ("#procs\tfrequency\n"); for (i = 0; i <= num_created_processes - 1; i++) printf ("%d\t%d\n", i, invalidation_set_size_histogram[i]); printf ("\n"); if (invalidation_set_size_samples > 0) printf ("avg. invalidation set size = %.2f\n", (double)invalidation_set_size_sum / invalidation_set_size_samples); else printf ("avg. invalidation set size = 0\n"); total_bus_requests = total_read_requests + total_read_excl_requests + total_upgrade_requests; printf ("\n"); printf ("===== Total bus activity statistics =====\n"); printf ("\n"); printf ("total_requests\t\t%d\n", total_bus_requests); printf ("\n"); printf ("read_requests\t\t%d\t(%5.2f%% of all requests)\n", total_read_requests, (double) total_read_requests / total_bus_requests * 100.0); printf (" cache-to-cache xfers\t%d\t\t(%5.2f%% of total_read_requests)\n", total_shared_responses, (double) total_shared_responses / total_read_requests * 100.0); printf ("read_excl_requests\t%d\t(%5.2f%% of all requests)\n", total_read_excl_requests, (double) total_read_excl_requests / total_bus_requests * 100.0); printf (" cache-to-cache xfers\t%d\t\t(%5.2f%% of total_read_excl_requests)\n", total_exclusive_responses, (double) total_exclusive_responses / total_read_excl_requests * 100.0); printf ("upgrade_requests\t%d\t(%5.2f%% of all requests)\n", total_upgrade_requests, (double) total_upgrade_requests / total_bus_requests * 100.0); printf ("\n"); printf ("read & read_excl requests\t%d\t(%5.2f%% of all requests)\n", total_read_requests + total_read_excl_requests, (double) (total_read_requests + total_read_excl_requests) / total_bus_requests * 100.0); printf ("total_mem_writebacks\t\t%d\t(%5.2f%% of read/read_excl)\n", total_mem_writebacks, (double) total_mem_writebacks / (total_read_requests + total_read_excl_requests) * 100.0); printf ("sharing_writebacks\t\t%d\n", total_shared_responses); printf ("writebacks per read/read_excl\t%.2f\n", (double) (total_mem_writebacks + total_shared_responses) / (total_read_requests + total_read_excl_requests)); printf ("writebacks per bus request\t%.2f\n", (double) (total_mem_writebacks + total_shared_responses) / total_bus_requests);#ifdef GRAPHICS /* if graphics enabled for this run, pause before terminating so that the final cache contents displayed on the screen may be viewed as long as necessary; print message on the graphics window to press return to continue (if window gets obscured after this point, it will not be refreshed; making the appropriate modifications for full refresh capability is left as an exercise for the reader.....) */ if (graphics_flag) { char s[128]; SetColor (BLACK); DrawLeftString ("Simulation complete; press return in the shell window" " to terminate", 10, WIN_HEIGHT - 20); FlushWindow (); /* print the same message to shell window */ printf ("\nSimulation complete; press return to terminate\n"); fflush (stdout); gets (s); }#endif /* GRAPHICS */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -