diff options
Diffstat (limited to 'src/accelwattch/gpgpu_sim_wrapper.cc')
| -rw-r--r-- | src/accelwattch/gpgpu_sim_wrapper.cc | 1143 |
1 files changed, 1143 insertions, 0 deletions
diff --git a/src/accelwattch/gpgpu_sim_wrapper.cc b/src/accelwattch/gpgpu_sim_wrapper.cc new file mode 100644 index 0000000..67d9daa --- /dev/null +++ b/src/accelwattch/gpgpu_sim_wrapper.cc @@ -0,0 +1,1143 @@ +// Copyright (c) 2009-2021, Tor M. Aamodt, Tayler Hetherington, Ahmed ElTantawy, Vijay Kandiah, Nikos Hardavellas +// The University of British Columbia, Northwestern University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include "gpgpu_sim_wrapper.h" +#include <sys/stat.h> +#define SP_BASE_POWER 0 +#define SFU_BASE_POWER 0 + +static const char* pwr_cmp_label[] = { + "IBP,", "ICP,", "DCP,", "TCP,", "CCP,", "SHRDP,", "RFP,", "INTP,", + "FPUP,", "DPUP,", "INT_MUL24P,", "INT_MUL32P,", "INT_MULP,", "INT_DIVP,", + "FP_MULP,", "FP_DIVP,", "FP_SQRTP,", "FP_LGP,", "FP_SINP,", "FP_EXP,", + "DP_MULP,", "DP_DIVP,", "TENSORP,", "TEXP,", "SCHEDP,", "L2CP,", "MCP,", "NOCP,", + "DRAMP,", "PIPEP,", "IDLE_COREP,", "CONSTP", "STATICP"}; + +enum pwr_cmp_t { + IBP=0, + ICP, + DCP, + TCP, + CCP, + SHRDP, + RFP, + INTP, + FPUP, + DPUP, + INT_MUL24P, + INT_MUL32P, + INT_MULP, + INT_DIVP, + FP_MULP, + FP_DIVP, + FP_SQRTP, + FP_LGP, + FP_SINP, + FP_EXP, + DP_MULP, + DP_DIVP, + TENSORP, + TEXP, + SCHEDP, + L2CP, + MCP, + NOCP, + DRAMP, + PIPEP, + IDLE_COREP, + CONSTP, + STATICP, + NUM_COMPONENTS_MODELLED +}; + +gpgpu_sim_wrapper::gpgpu_sim_wrapper(bool power_simulation_enabled, + char* xmlfile, int power_simulation_mode, bool dvfs_enabled) { + kernel_sample_count = 0; + total_sample_count = 0; + + kernel_tot_power = 0; + avg_threads_per_warp_tot = 0; + num_pwr_cmps = NUM_COMPONENTS_MODELLED; + num_perf_counters = NUM_PERFORMANCE_COUNTERS; + + // Initialize per-component counter/power vectors + avg_max_min_counters<double> init; + kernel_cmp_pwr.resize(NUM_COMPONENTS_MODELLED, init); + kernel_cmp_perf_counters.resize(NUM_PERFORMANCE_COUNTERS, init); + + kernel_power = init; // Per-kernel powers + gpu_tot_power = init; // Global powers + + sample_cmp_pwr.resize(NUM_COMPONENTS_MODELLED, 0); + + sample_perf_counters.resize(NUM_PERFORMANCE_COUNTERS, 0); + initpower_coeff.resize(NUM_PERFORMANCE_COUNTERS, 0); + effpower_coeff.resize(NUM_PERFORMANCE_COUNTERS, 0); + + const_dynamic_power = 0; + proc_power = 0; + + g_power_filename = NULL; + g_power_trace_filename = NULL; + g_metric_trace_filename = NULL; + g_steady_state_tracking_filename = NULL; + xml_filename = xmlfile; + g_power_simulation_enabled = power_simulation_enabled; + g_power_simulation_mode = power_simulation_mode; + g_dvfs_enabled = dvfs_enabled; + g_power_trace_enabled = false; + g_steady_power_levels_enabled = false; + g_power_trace_zlevel = 0; + g_power_per_cycle_dump = false; + gpu_steady_power_deviation = 0; + gpu_steady_min_period = 0; + + gpu_stat_sample_freq = 0; + p = new ParseXML(); + if (g_power_simulation_enabled) { + p->parse(xml_filename); + } + proc = new Processor(p); + power_trace_file = NULL; + metric_trace_file = NULL; + steady_state_tacking_file = NULL; + has_written_avg = false; + init_inst_val = false; +} + +gpgpu_sim_wrapper::~gpgpu_sim_wrapper() {} + +bool gpgpu_sim_wrapper::sanity_check(double a, double b) { + if (b == 0) + return (abs(a - b) < 0.00001); + else + return (abs(a - b) / abs(b) < 0.00001); + + return false; +} +void gpgpu_sim_wrapper::init_mcpat_hw_mode(unsigned gpu_sim_cycle) { + p->sys.total_cycles = gpu_sim_cycle; //total simulated cycles for current kernel +} + +void gpgpu_sim_wrapper::init_mcpat( + char* xmlfile, char* powerfilename, char* power_trace_filename, + char* metric_trace_filename, char* steady_state_filename, + bool power_sim_enabled, bool trace_enabled, bool steady_state_enabled, + bool power_per_cycle_dump, double steady_power_deviation, + double steady_min_period, int zlevel, double init_val, + int stat_sample_freq, int power_sim_mode, bool dvfs_enabled, + unsigned clock_freq, unsigned num_shaders) { + // Write File Headers for (-metrics trace, -power trace) + + reset_counters(); + static bool mcpat_init = true; + + // initialize file name if it is not set + time_t curr_time; + time(&curr_time); + char* date = ctime(&curr_time); + char* s = date; + while (*s) { + if (*s == ' ' || *s == '\t' || *s == ':') *s = '-'; + if (*s == '\n' || *s == '\r') *s = 0; + s++; + } + + if (mcpat_init) { + g_power_filename = powerfilename; + g_power_trace_filename = power_trace_filename; + g_metric_trace_filename = metric_trace_filename; + g_steady_state_tracking_filename = steady_state_filename; + xml_filename = xmlfile; + g_power_simulation_enabled = power_sim_enabled; + g_power_simulation_mode = power_sim_mode; + g_dvfs_enabled = dvfs_enabled; + g_power_trace_enabled = trace_enabled; + g_steady_power_levels_enabled = steady_state_enabled; + g_power_trace_zlevel = zlevel; + g_power_per_cycle_dump = power_per_cycle_dump; + gpu_steady_power_deviation = steady_power_deviation; + gpu_steady_min_period = steady_min_period; + + gpu_stat_sample_freq = stat_sample_freq; + + // p->sys.total_cycles=gpu_stat_sample_freq*4; + p->sys.total_cycles = gpu_stat_sample_freq; + p->sys.target_core_clockrate = clock_freq; + p->sys.number_of_cores = num_shaders; + p->sys.core[0].clock_rate = clock_freq; + power_trace_file = NULL; + metric_trace_file = NULL; + steady_state_tacking_file = NULL; + + if (g_power_trace_enabled) { + power_trace_file = gzopen(g_power_trace_filename, "w"); + metric_trace_file = gzopen(g_metric_trace_filename, "w"); + if ((power_trace_file == NULL) || (metric_trace_file == NULL)) { + printf("error - could not open trace files \n"); + exit(1); + } + gzsetparams(power_trace_file, g_power_trace_zlevel, Z_DEFAULT_STRATEGY); + + gzprintf(power_trace_file, "power,"); + for (unsigned i = 0; i < num_pwr_cmps; i++) { + gzprintf(power_trace_file, pwr_cmp_label[i]); + } + gzprintf(power_trace_file, "\n"); + + gzsetparams(metric_trace_file, g_power_trace_zlevel, Z_DEFAULT_STRATEGY); + for (unsigned i = 0; i < num_perf_counters; i++) { + gzprintf(metric_trace_file, perf_count_label[i]); + } + gzprintf(metric_trace_file, "\n"); + + gzclose(power_trace_file); + gzclose(metric_trace_file); + } + if (g_steady_power_levels_enabled) { + steady_state_tacking_file = gzopen(g_steady_state_tracking_filename, "w"); + if ((steady_state_tacking_file == NULL)) { + printf("error - could not open trace files \n"); + exit(1); + } + gzsetparams(steady_state_tacking_file, g_power_trace_zlevel, + Z_DEFAULT_STRATEGY); + gzprintf(steady_state_tacking_file, "start,end,power,IPC,"); + for (unsigned i = 0; i < num_perf_counters; i++) { + gzprintf(steady_state_tacking_file, perf_count_label[i]); + } + gzprintf(steady_state_tacking_file, "\n"); + + gzclose(steady_state_tacking_file); + } + + mcpat_init = false; + has_written_avg = false; + powerfile.open(g_power_filename); + int flg = chmod(g_power_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + assert(flg == 0); + } + sample_val = 0; + init_inst_val = init_val; // gpu_tot_sim_insn+gpu_sim_insn; +} + +void gpgpu_sim_wrapper::reset_counters() { + avg_max_min_counters<double> init; + for (unsigned i = 0; i < num_perf_counters; ++i) { + sample_perf_counters[i] = 0; + kernel_cmp_perf_counters[i] = init; + } + for (unsigned i = 0; i < num_pwr_cmps; ++i) { + sample_cmp_pwr[i] = 0; + kernel_cmp_pwr[i] = init; + } + + // Reset per-kernel counters + kernel_sample_count = 0; + kernel_tot_power = 0; + kernel_power = init; + avg_threads_per_warp_tot = 0; + return; +} + +void gpgpu_sim_wrapper::set_inst_power(bool clk_gated_lanes, double tot_cycles, + double busy_cycles, double tot_inst, + double int_inst, double fp_inst, + double load_inst, double store_inst, + double committed_inst) { + p->sys.core[0].gpgpu_clock_gated_lanes = clk_gated_lanes; + p->sys.core[0].total_cycles = tot_cycles; + p->sys.core[0].busy_cycles = busy_cycles; + p->sys.core[0].total_instructions = + tot_inst * p->sys.scaling_coefficients[TOT_INST]; + p->sys.core[0].int_instructions = + int_inst * p->sys.scaling_coefficients[FP_INT]; + p->sys.core[0].fp_instructions = + fp_inst * p->sys.scaling_coefficients[FP_INT]; + p->sys.core[0].load_instructions = load_inst; + p->sys.core[0].store_instructions = store_inst; + p->sys.core[0].committed_instructions = committed_inst; + sample_perf_counters[FP_INT] = int_inst + fp_inst; + sample_perf_counters[TOT_INST] = tot_inst; +} + +void gpgpu_sim_wrapper::set_regfile_power(double reads, double writes, + double ops) { + p->sys.core[0].int_regfile_reads = + reads * p->sys.scaling_coefficients[REG_RD]; + p->sys.core[0].int_regfile_writes = + writes * p->sys.scaling_coefficients[REG_WR]; + p->sys.core[0].non_rf_operands = + ops * p->sys.scaling_coefficients[NON_REG_OPs]; + sample_perf_counters[REG_RD] = reads; + sample_perf_counters[REG_WR] = writes; + sample_perf_counters[NON_REG_OPs] = ops; +} + +void gpgpu_sim_wrapper::set_icache_power(double hits, double misses) { + p->sys.core[0].icache.read_accesses = + hits * p->sys.scaling_coefficients[IC_H] + + misses * p->sys.scaling_coefficients[IC_M]; + p->sys.core[0].icache.read_misses = + misses * p->sys.scaling_coefficients[IC_M]; + sample_perf_counters[IC_H] = hits; + sample_perf_counters[IC_M] = misses; +} + +void gpgpu_sim_wrapper::set_ccache_power(double hits, double misses) { + p->sys.core[0].ccache.read_accesses = + hits * p->sys.scaling_coefficients[CC_H] + + misses * p->sys.scaling_coefficients[CC_M]; + p->sys.core[0].ccache.read_misses = + misses * p->sys.scaling_coefficients[CC_M]; + sample_perf_counters[CC_H] = hits; + sample_perf_counters[CC_M] = misses; + // TODO: coalescing logic is counted as part of the caches power (this is not + // valid for no-caches architectures) +} + +void gpgpu_sim_wrapper::set_tcache_power(double hits, double misses) { + p->sys.core[0].tcache.read_accesses = + hits * p->sys.scaling_coefficients[TC_H] + + misses * p->sys.scaling_coefficients[TC_M]; + p->sys.core[0].tcache.read_misses = + misses * p->sys.scaling_coefficients[TC_M]; + sample_perf_counters[TC_H] = hits; + sample_perf_counters[TC_M] = misses; + // TODO: coalescing logic is counted as part of the caches power (this is not + // valid for no-caches architectures) +} + +void gpgpu_sim_wrapper::set_shrd_mem_power(double accesses) { + p->sys.core[0].sharedmemory.read_accesses = + accesses * p->sys.scaling_coefficients[SHRD_ACC]; + sample_perf_counters[SHRD_ACC] = accesses; +} + +void gpgpu_sim_wrapper::set_l1cache_power(double read_hits, double read_misses, + double write_hits, + double write_misses) { + p->sys.core[0].dcache.read_accesses = + read_hits * p->sys.scaling_coefficients[DC_RH] + + read_misses * p->sys.scaling_coefficients[DC_RM]; + p->sys.core[0].dcache.read_misses = + read_misses * p->sys.scaling_coefficients[DC_RM]; + p->sys.core[0].dcache.write_accesses = + write_hits * p->sys.scaling_coefficients[DC_WH] + + write_misses * p->sys.scaling_coefficients[DC_WM]; + p->sys.core[0].dcache.write_misses = + write_misses * p->sys.scaling_coefficients[DC_WM]; + sample_perf_counters[DC_RH] = read_hits; + sample_perf_counters[DC_RM] = read_misses; + sample_perf_counters[DC_WH] = write_hits; + sample_perf_counters[DC_WM] = write_misses; + // TODO: coalescing logic is counted as part of the caches power (this is not + // valid for no-caches architectures) +} + +void gpgpu_sim_wrapper::set_l2cache_power(double read_hits, double read_misses, + double write_hits, + double write_misses) { + p->sys.l2.total_accesses = read_hits * p->sys.scaling_coefficients[L2_RH] + + read_misses * p->sys.scaling_coefficients[L2_RM] + + write_hits * p->sys.scaling_coefficients[L2_WH] + + write_misses * p->sys.scaling_coefficients[L2_WM]; + p->sys.l2.read_accesses = read_hits * p->sys.scaling_coefficients[L2_RH] + + read_misses * p->sys.scaling_coefficients[L2_RM]; + p->sys.l2.write_accesses = write_hits * p->sys.scaling_coefficients[L2_WH] + + write_misses * p->sys.scaling_coefficients[L2_WM]; + p->sys.l2.read_hits = read_hits * p->sys.scaling_coefficients[L2_RH]; + p->sys.l2.read_misses = read_misses * p->sys.scaling_coefficients[L2_RM]; + p->sys.l2.write_hits = write_hits * p->sys.scaling_coefficients[L2_WH]; + p->sys.l2.write_misses = write_misses * p->sys.scaling_coefficients[L2_WM]; + sample_perf_counters[L2_RH] = read_hits; + sample_perf_counters[L2_RM] = read_misses; + sample_perf_counters[L2_WH] = write_hits; + sample_perf_counters[L2_WM] = write_misses; +} + +void gpgpu_sim_wrapper::set_num_cores(double num_core) { + + num_cores = num_core; +} + +void gpgpu_sim_wrapper::set_idle_core_power(double num_idle_core) { + p->sys.num_idle_cores = num_idle_core; + sample_perf_counters[IDLE_CORE_N] = num_idle_core; + num_idle_cores = num_idle_core; +} + +void gpgpu_sim_wrapper::set_duty_cycle_power(double duty_cycle) { + p->sys.core[0].pipeline_duty_cycle = + duty_cycle * p->sys.scaling_coefficients[PIPE_A]; + sample_perf_counters[PIPE_A] = duty_cycle; +} + +void gpgpu_sim_wrapper::set_mem_ctrl_power(double reads, double writes, + double dram_precharge) { + p->sys.mc.memory_accesses = reads * p->sys.scaling_coefficients[MEM_RD] + + writes * p->sys.scaling_coefficients[MEM_WR]; + p->sys.mc.memory_reads = reads * p->sys.scaling_coefficients[MEM_RD]; + p->sys.mc.memory_writes = writes * p->sys.scaling_coefficients[MEM_WR]; + p->sys.mc.dram_pre = dram_precharge * p->sys.scaling_coefficients[MEM_PRE]; + sample_perf_counters[MEM_RD] = reads; + sample_perf_counters[MEM_WR] = writes; + sample_perf_counters[MEM_PRE] = dram_precharge; +} + + +void gpgpu_sim_wrapper::set_model_voltage(double model_voltage) { + modeled_chip_voltage = model_voltage; +} + + +void gpgpu_sim_wrapper::set_exec_unit_power(double fpu_accesses, + double ialu_accesses, + double sfu_accesses) { + p->sys.core[0].fpu_accesses = fpu_accesses; + tot_fpu_accesses = fpu_accesses; + //Integer ALU (not present in Tesla) + p->sys.core[0].ialu_accesses = ialu_accesses; + + //Sfu accesses + p->sys.core[0].mul_accesses = sfu_accesses; + tot_sfu_accesses = sfu_accesses; +} + +PowerscalingCoefficients * gpgpu_sim_wrapper::get_scaling_coeffs() +{ + + PowerscalingCoefficients * scalingCoeffs = new PowerscalingCoefficients(); + + scalingCoeffs->int_coeff = p->sys.scaling_coefficients[INT_ACC]; + scalingCoeffs->int_mul_coeff = p->sys.scaling_coefficients[INT_MUL_ACC]; + scalingCoeffs->int_mul24_coeff = p->sys.scaling_coefficients[INT_MUL24_ACC]; + scalingCoeffs->int_mul32_coeff = p->sys.scaling_coefficients[INT_MUL32_ACC]; + scalingCoeffs->int_div_coeff = p->sys.scaling_coefficients[INT_DIV_ACC]; + scalingCoeffs->fp_coeff = p->sys.scaling_coefficients[FP_ACC]; + scalingCoeffs->dp_coeff = p->sys.scaling_coefficients[DP_ACC]; + scalingCoeffs->fp_mul_coeff = p->sys.scaling_coefficients[FP_MUL_ACC]; + scalingCoeffs->fp_div_coeff = p->sys.scaling_coefficients[FP_DIV_ACC]; + scalingCoeffs->dp_mul_coeff = p->sys.scaling_coefficients[DP_MUL_ACC]; + scalingCoeffs->dp_div_coeff = p->sys.scaling_coefficients[DP_DIV_ACC]; + scalingCoeffs->sqrt_coeff = p->sys.scaling_coefficients[FP_SQRT_ACC]; + scalingCoeffs->log_coeff = p->sys.scaling_coefficients[FP_LG_ACC]; + scalingCoeffs->sin_coeff = p->sys.scaling_coefficients[FP_SIN_ACC]; + scalingCoeffs->exp_coeff = p->sys.scaling_coefficients[FP_EXP_ACC]; + scalingCoeffs->tensor_coeff = p->sys.scaling_coefficients[TENSOR_ACC]; + scalingCoeffs->tex_coeff = p->sys.scaling_coefficients[TEX_ACC]; + return scalingCoeffs; + +} + +void gpgpu_sim_wrapper::set_int_accesses(double ialu_accesses, + double imul24_accesses, + double imul32_accesses, + double imul_accesses, + double idiv_accesses) +{ + + sample_perf_counters[INT_ACC]=ialu_accesses; + sample_perf_counters[INT_MUL24_ACC]=imul24_accesses; + sample_perf_counters[INT_MUL32_ACC]=imul32_accesses; + sample_perf_counters[INT_MUL_ACC]=imul_accesses; + sample_perf_counters[INT_DIV_ACC]=idiv_accesses; +} + +void gpgpu_sim_wrapper::set_dp_accesses(double dpu_accesses, + double dpmul_accesses, + double dpdiv_accesses) +{ + sample_perf_counters[DP_ACC]=dpu_accesses; + sample_perf_counters[DP_MUL_ACC]=dpmul_accesses; + sample_perf_counters[DP_DIV_ACC]=dpdiv_accesses; +} + +void gpgpu_sim_wrapper::set_fp_accesses(double fpu_accesses, + double fpmul_accesses, + double fpdiv_accesses) +{ + sample_perf_counters[FP_ACC]=fpu_accesses; + sample_perf_counters[FP_MUL_ACC]=fpmul_accesses; + sample_perf_counters[FP_DIV_ACC]=fpdiv_accesses; +} + +void gpgpu_sim_wrapper::set_trans_accesses(double sqrt_accesses, + double log_accesses, + double sin_accesses, + double exp_accesses) +{ + + sample_perf_counters[FP_SQRT_ACC]=sqrt_accesses; + sample_perf_counters[FP_LG_ACC]=log_accesses; + sample_perf_counters[FP_SIN_ACC]=sin_accesses; + sample_perf_counters[FP_EXP_ACC]=exp_accesses; + +} + +void gpgpu_sim_wrapper::set_tensor_accesses(double tensor_accesses) +{ + sample_perf_counters[TENSOR_ACC]=tensor_accesses; + +} + +void gpgpu_sim_wrapper::set_tex_accesses(double tex_accesses) +{ + sample_perf_counters[TEX_ACC]=tex_accesses; + +} + +void gpgpu_sim_wrapper::set_avg_active_threads(float active_threads) +{ + avg_threads_per_warp = (unsigned)ceil(active_threads); + avg_threads_per_warp_tot += active_threads; +} + +void gpgpu_sim_wrapper::set_active_lanes_power(double sp_avg_active_lane, + double sfu_avg_active_lane) { + p->sys.core[0].sp_average_active_lanes = sp_avg_active_lane; + p->sys.core[0].sfu_average_active_lanes = sfu_avg_active_lane; +} + +void gpgpu_sim_wrapper::set_NoC_power(double noc_tot_acc) { + p->sys.NoC[0].total_accesses = + noc_tot_acc * p->sys.scaling_coefficients[NOC_A]; + sample_perf_counters[NOC_A] = noc_tot_acc; +} + +void gpgpu_sim_wrapper::power_metrics_calculations() { + total_sample_count++; + kernel_sample_count++; + + // Current sample power + double sample_power = proc->rt_power.readOp.dynamic + sample_cmp_pwr[CONSTP] + sample_cmp_pwr[STATICP]; + // double sample_power; + // for(unsigned i=0; i<num_pwr_cmps; i++){ + // sample_power+=sample_cmp_pwr[i]; //fix for dvfs + // } + + // Average power + // Previous + new + constant dynamic power (e.g., dynamic clocking power) + kernel_tot_power += sample_power; + kernel_power.avg = kernel_tot_power / kernel_sample_count; + for (unsigned ind = 0; ind < num_pwr_cmps; ++ind) { + kernel_cmp_pwr[ind].avg += (double)sample_cmp_pwr[ind]; + } + + for (unsigned ind = 0; ind < num_perf_counters; ++ind) { + kernel_cmp_perf_counters[ind].avg += (double)sample_perf_counters[ind]; + } + + // Max Power + if (sample_power > kernel_power.max) { + kernel_power.max = sample_power; + for (unsigned ind = 0; ind < num_pwr_cmps; ++ind) { + kernel_cmp_pwr[ind].max = (double)sample_cmp_pwr[ind]; + } + for (unsigned ind = 0; ind < num_perf_counters; ++ind) { + kernel_cmp_perf_counters[ind].max = sample_perf_counters[ind]; + } + } + + // Min Power + if (sample_power < kernel_power.min || (kernel_power.min == 0)) { + kernel_power.min = sample_power; + for (unsigned ind = 0; ind < num_pwr_cmps; ++ind) { + kernel_cmp_pwr[ind].min = (double)sample_cmp_pwr[ind]; + } + for (unsigned ind = 0; ind < num_perf_counters; ++ind) { + kernel_cmp_perf_counters[ind].min = sample_perf_counters[ind]; + } + } + + gpu_tot_power.avg = (gpu_tot_power.avg + sample_power); + gpu_tot_power.max = + (sample_power > gpu_tot_power.max) ? sample_power : gpu_tot_power.max; + gpu_tot_power.min = + ((sample_power < gpu_tot_power.min) || (gpu_tot_power.min == 0)) + ? sample_power + : gpu_tot_power.min; +} + +void gpgpu_sim_wrapper::print_trace_files() { + open_files(); + + for (unsigned i = 0; i < num_perf_counters; ++i) { + gzprintf(metric_trace_file, "%f,", sample_perf_counters[i]); + } + gzprintf(metric_trace_file, "\n"); + + gzprintf(power_trace_file, "%f,", proc_power); + for (unsigned i = 0; i < num_pwr_cmps; ++i) { + gzprintf(power_trace_file, "%f,", sample_cmp_pwr[i]); + } + gzprintf(power_trace_file, "\n"); + + close_files(); +} + +void gpgpu_sim_wrapper::update_coefficients() +{ + + initpower_coeff[FP_INT]=proc->cores[0]->get_coefficient_fpint_insts(); + effpower_coeff[FP_INT]=initpower_coeff[FP_INT] * p->sys.scaling_coefficients[FP_INT]; + + initpower_coeff[TOT_INST]=proc->cores[0]->get_coefficient_tot_insts(); + effpower_coeff[TOT_INST]=initpower_coeff[TOT_INST] * p->sys.scaling_coefficients[TOT_INST]; + + initpower_coeff[REG_RD]=proc->cores[0]->get_coefficient_regreads_accesses()*(proc->cores[0]->exu->rf_fu_clockRate/proc->cores[0]->exu->clockRate); + initpower_coeff[REG_WR]=proc->cores[0]->get_coefficient_regwrites_accesses()*(proc->cores[0]->exu->rf_fu_clockRate/proc->cores[0]->exu->clockRate); + initpower_coeff[NON_REG_OPs]=proc->cores[0]->get_coefficient_noregfileops_accesses()*(proc->cores[0]->exu->rf_fu_clockRate/proc->cores[0]->exu->clockRate); + effpower_coeff[REG_RD]=initpower_coeff[REG_RD]*p->sys.scaling_coefficients[REG_RD]; + effpower_coeff[REG_WR]=initpower_coeff[REG_WR]*p->sys.scaling_coefficients[REG_WR]; + effpower_coeff[NON_REG_OPs]=initpower_coeff[NON_REG_OPs]*p->sys.scaling_coefficients[NON_REG_OPs]; + + initpower_coeff[IC_H]=proc->cores[0]->get_coefficient_icache_hits(); + initpower_coeff[IC_M]=proc->cores[0]->get_coefficient_icache_misses(); + effpower_coeff[IC_H]=initpower_coeff[IC_H]*p->sys.scaling_coefficients[IC_H]; + effpower_coeff[IC_M]=initpower_coeff[IC_M]*p->sys.scaling_coefficients[IC_M]; + + initpower_coeff[CC_H]=(proc->cores[0]->get_coefficient_ccache_readhits()+proc->get_coefficient_readcoalescing()); + initpower_coeff[CC_M]=(proc->cores[0]->get_coefficient_ccache_readmisses()+proc->get_coefficient_readcoalescing()); + effpower_coeff[CC_H]=initpower_coeff[CC_H]*p->sys.scaling_coefficients[CC_H]; + effpower_coeff[CC_M]=initpower_coeff[CC_M]*p->sys.scaling_coefficients[CC_M]; + + initpower_coeff[TC_H]=(proc->cores[0]->get_coefficient_tcache_readhits()+proc->get_coefficient_readcoalescing()); + initpower_coeff[TC_M]=(proc->cores[0]->get_coefficient_tcache_readmisses()+proc->get_coefficient_readcoalescing()); + effpower_coeff[TC_H]=initpower_coeff[TC_H]*p->sys.scaling_coefficients[TC_H]; + effpower_coeff[TC_M]=initpower_coeff[TC_M]*p->sys.scaling_coefficients[TC_M]; + + initpower_coeff[SHRD_ACC]=proc->cores[0]->get_coefficient_sharedmemory_readhits(); + effpower_coeff[SHRD_ACC]=initpower_coeff[SHRD_ACC]*p->sys.scaling_coefficients[SHRD_ACC]; + + initpower_coeff[DC_RH]=(proc->cores[0]->get_coefficient_dcache_readhits() + proc->get_coefficient_readcoalescing()); + initpower_coeff[DC_RM]=(proc->cores[0]->get_coefficient_dcache_readmisses() + proc->get_coefficient_readcoalescing()); + initpower_coeff[DC_WH]=(proc->cores[0]->get_coefficient_dcache_writehits() + proc->get_coefficient_writecoalescing()); + initpower_coeff[DC_WM]=(proc->cores[0]->get_coefficient_dcache_writemisses() + proc->get_coefficient_writecoalescing()); + effpower_coeff[DC_RH]=initpower_coeff[DC_RH]*p->sys.scaling_coefficients[DC_RH]; + effpower_coeff[DC_RM]=initpower_coeff[DC_RM]*p->sys.scaling_coefficients[DC_RM]; + effpower_coeff[DC_WH]=initpower_coeff[DC_WH]*p->sys.scaling_coefficients[DC_WH]; + effpower_coeff[DC_WM]=initpower_coeff[DC_WM]*p->sys.scaling_coefficients[DC_WM]; + + initpower_coeff[L2_RH]=proc->get_coefficient_l2_read_hits(); + initpower_coeff[L2_RM]=proc->get_coefficient_l2_read_misses(); + initpower_coeff[L2_WH]=proc->get_coefficient_l2_write_hits(); + initpower_coeff[L2_WM]=proc->get_coefficient_l2_write_misses(); + effpower_coeff[L2_RH]=initpower_coeff[L2_RH]*p->sys.scaling_coefficients[L2_RH]; + effpower_coeff[L2_RM]=initpower_coeff[L2_RM]*p->sys.scaling_coefficients[L2_RM]; + effpower_coeff[L2_WH]=initpower_coeff[L2_WH]*p->sys.scaling_coefficients[L2_WH]; + effpower_coeff[L2_WM]=initpower_coeff[L2_WM]*p->sys.scaling_coefficients[L2_WM]; + + initpower_coeff[IDLE_CORE_N]=p->sys.idle_core_power * proc->cores[0]->executionTime; + effpower_coeff[IDLE_CORE_N]=initpower_coeff[IDLE_CORE_N]*p->sys.scaling_coefficients[IDLE_CORE_N]; + + initpower_coeff[PIPE_A]=proc->cores[0]->get_coefficient_duty_cycle(); + effpower_coeff[PIPE_A]=initpower_coeff[PIPE_A]*p->sys.scaling_coefficients[PIPE_A]; + + initpower_coeff[MEM_RD]=proc->get_coefficient_mem_reads(); + initpower_coeff[MEM_WR]=proc->get_coefficient_mem_writes(); + initpower_coeff[MEM_PRE]=proc->get_coefficient_mem_pre(); + effpower_coeff[MEM_RD]=initpower_coeff[MEM_RD]*p->sys.scaling_coefficients[MEM_RD]; + effpower_coeff[MEM_WR]=initpower_coeff[MEM_WR]*p->sys.scaling_coefficients[MEM_WR]; + effpower_coeff[MEM_PRE]=initpower_coeff[MEM_PRE]*p->sys.scaling_coefficients[MEM_PRE]; + + double fp_coeff = proc->cores[0]->get_coefficient_fpu_accesses(); + double sfu_coeff = proc->cores[0]->get_coefficient_sfu_accesses(); + + initpower_coeff[INT_ACC]= proc->cores[0]->get_coefficient_ialu_accesses()*(proc->cores[0]->exu->rf_fu_clockRate/proc->cores[0]->exu->clockRate); + + if(tot_fpu_accesses != 0){ + initpower_coeff[FP_ACC]= fp_coeff * sample_perf_counters[FP_ACC]/tot_fpu_accesses; + initpower_coeff[DP_ACC]= fp_coeff * sample_perf_counters[DP_ACC]/tot_fpu_accesses; + } + else{ + initpower_coeff[FP_ACC]= 0; + initpower_coeff[DP_ACC]= 0; + } + + if(tot_sfu_accesses != 0){ + initpower_coeff[INT_MUL24_ACC]= sfu_coeff * sample_perf_counters[INT_MUL24_ACC]/tot_sfu_accesses; + initpower_coeff[INT_MUL32_ACC]= sfu_coeff * sample_perf_counters[INT_MUL32_ACC]/tot_sfu_accesses; + initpower_coeff[INT_MUL_ACC]= sfu_coeff * sample_perf_counters[INT_MUL_ACC]/tot_sfu_accesses; + initpower_coeff[INT_DIV_ACC]= sfu_coeff * sample_perf_counters[INT_DIV_ACC]/tot_sfu_accesses; + initpower_coeff[DP_MUL_ACC]= sfu_coeff * sample_perf_counters[DP_MUL_ACC]/tot_sfu_accesses; + initpower_coeff[DP_DIV_ACC]= sfu_coeff * sample_perf_counters[DP_DIV_ACC]/tot_sfu_accesses; + initpower_coeff[FP_MUL_ACC]= sfu_coeff * sample_perf_counters[FP_MUL_ACC]/tot_sfu_accesses; + initpower_coeff[FP_DIV_ACC]= sfu_coeff * sample_perf_counters[FP_DIV_ACC]/tot_sfu_accesses; + initpower_coeff[FP_SQRT_ACC]= sfu_coeff * sample_perf_counters[FP_SQRT_ACC]/tot_sfu_accesses; + initpower_coeff[FP_LG_ACC]= sfu_coeff * sample_perf_counters[FP_LG_ACC]/tot_sfu_accesses; + initpower_coeff[FP_SIN_ACC]= sfu_coeff * sample_perf_counters[FP_SIN_ACC]/tot_sfu_accesses; + initpower_coeff[FP_EXP_ACC]= sfu_coeff * sample_perf_counters[FP_EXP_ACC]/tot_sfu_accesses; + initpower_coeff[TENSOR_ACC]= sfu_coeff * sample_perf_counters[TENSOR_ACC]/tot_sfu_accesses; + initpower_coeff[TEX_ACC]= sfu_coeff * sample_perf_counters[TEX_ACC]/tot_sfu_accesses; + } + else{ + initpower_coeff[INT_MUL24_ACC]= 0; + initpower_coeff[INT_MUL32_ACC]= 0; + initpower_coeff[INT_MUL_ACC]= 0; + initpower_coeff[INT_DIV_ACC]= 0; + initpower_coeff[DP_MUL_ACC]= 0; + initpower_coeff[DP_DIV_ACC]= 0; + initpower_coeff[FP_MUL_ACC]= 0; + initpower_coeff[FP_DIV_ACC]= 0; + initpower_coeff[FP_SQRT_ACC]= 0; + initpower_coeff[FP_LG_ACC]= 0; + initpower_coeff[FP_SIN_ACC]= 0; + initpower_coeff[FP_EXP_ACC]= 0; + initpower_coeff[TENSOR_ACC]= 0; + initpower_coeff[TEX_ACC]= 0; + } + + effpower_coeff[INT_ACC]= initpower_coeff[INT_ACC]; + effpower_coeff[FP_ACC]= initpower_coeff[FP_ACC]; + effpower_coeff[DP_ACC]= initpower_coeff[DP_ACC]; + effpower_coeff[INT_MUL24_ACC]= initpower_coeff[INT_MUL24_ACC]; + effpower_coeff[INT_MUL32_ACC]= initpower_coeff[INT_MUL32_ACC]; + effpower_coeff[INT_MUL_ACC]= initpower_coeff[INT_MUL_ACC]; + effpower_coeff[INT_DIV_ACC]= initpower_coeff[INT_DIV_ACC]; + effpower_coeff[DP_MUL_ACC]= initpower_coeff[DP_MUL_ACC]; + effpower_coeff[DP_DIV_ACC]= initpower_coeff[DP_DIV_ACC]; + effpower_coeff[FP_MUL_ACC]= initpower_coeff[FP_MUL_ACC]; + effpower_coeff[FP_DIV_ACC]= initpower_coeff[FP_DIV_ACC]; + effpower_coeff[FP_SQRT_ACC]= initpower_coeff[FP_SQRT_ACC]; + effpower_coeff[FP_LG_ACC]= initpower_coeff[FP_LG_ACC]; + effpower_coeff[FP_SIN_ACC]= initpower_coeff[FP_SIN_ACC]; + effpower_coeff[FP_EXP_ACC]= initpower_coeff[FP_EXP_ACC]; + effpower_coeff[TENSOR_ACC]= initpower_coeff[TENSOR_ACC]; + effpower_coeff[TEX_ACC]= initpower_coeff[TEX_ACC]; + + initpower_coeff[NOC_A]=proc->get_coefficient_noc_accesses(); + effpower_coeff[NOC_A]=initpower_coeff[NOC_A]*p->sys.scaling_coefficients[NOC_A]; + + //const_dynamic_power=proc->get_const_dynamic_power()/(proc->cores[0]->executionTime); + + for(unsigned i=0; i<num_perf_counters; i++){ + initpower_coeff[i]/=(proc->cores[0]->executionTime); + effpower_coeff[i]/=(proc->cores[0]->executionTime); + } +} + +double gpgpu_sim_wrapper::calculate_static_power(){ + double int_accesses = initpower_coeff[INT_ACC] + initpower_coeff[INT_MUL24_ACC] + initpower_coeff[INT_MUL32_ACC] + initpower_coeff[INT_MUL_ACC] + initpower_coeff[INT_DIV_ACC]; + double int_add_accesses = initpower_coeff[INT_ACC]; + double int_mul_accesses = initpower_coeff[INT_MUL24_ACC] + initpower_coeff[INT_MUL32_ACC] + initpower_coeff[INT_MUL_ACC] + initpower_coeff[INT_DIV_ACC]; + double fp_accesses = initpower_coeff[FP_ACC] + initpower_coeff[FP_MUL_ACC] + initpower_coeff[FP_DIV_ACC]; + double dp_accesses = initpower_coeff[DP_ACC] + initpower_coeff[DP_MUL_ACC] + initpower_coeff[DP_DIV_ACC]; + double sfu_accesses = initpower_coeff[FP_SQRT_ACC] + initpower_coeff[FP_LG_ACC] + initpower_coeff[FP_SIN_ACC] + initpower_coeff[FP_EXP_ACC]; + double tensor_accesses = initpower_coeff[TENSOR_ACC]; + double tex_accesses = initpower_coeff[TEX_ACC]; + double total_static_power = 0.0; + double base_static_power = 0.0; + double lane_static_power = 0.0; + double per_active_core = (num_cores - num_idle_cores)/num_cores; + + + double l1_accesses = initpower_coeff[DC_RH] + initpower_coeff[DC_RM] + initpower_coeff[DC_WH] + initpower_coeff[DC_WM]; + double l2_accesses = initpower_coeff[L2_RH] + initpower_coeff[L2_RM] + initpower_coeff[L2_WH] + initpower_coeff[L2_WM]; + double shared_accesses = initpower_coeff[SHRD_ACC]; + + + if(avg_threads_per_warp == 0){ //no functional unit threads, check for memory or a 'LIGHT_SM' + if(l1_accesses != 0.0) + return (p->sys.static_l1_flane*per_active_core); + else if(shared_accesses != 0.0) + return (p->sys.static_shared_flane*per_active_core); + else if(l2_accesses != 0.0) + return (p->sys.static_l2_flane*per_active_core); + else //LIGHT_SM + return (p->sys.static_light_flane*per_active_core); //return LIGHT_SM base static power + } + + /* using a linear model for thread divergence */ + if((int_accesses != 0.0) && (fp_accesses != 0.0) && (dp_accesses != 0.0) && (sfu_accesses == 0.0) && (tensor_accesses == 0.0) && (tex_accesses == 0.0)){ + /* INT_FP_DP */ + base_static_power = p->sys.static_cat3_flane; + lane_static_power = p->sys.static_cat3_addlane; + } + + else if((int_accesses != 0.0) && (fp_accesses != 0.0) && (dp_accesses == 0.0) && (sfu_accesses == 0.0) && (tensor_accesses != 0.0) && (tex_accesses == 0.0)){ + /* INT_FP_TENSOR */ + base_static_power = p->sys.static_cat6_flane; + lane_static_power = p->sys.static_cat6_addlane; + } + + else if((int_accesses != 0.0) && (fp_accesses != 0.0) && (dp_accesses == 0.0) && (sfu_accesses != 0.0) && (tensor_accesses == 0.0) && (tex_accesses == 0.0)){ + /* INT_FP_SFU */ + base_static_power = p->sys.static_cat4_flane; + lane_static_power = p->sys.static_cat4_addlane; + } + + else if((int_accesses != 0.0) && (fp_accesses != 0.0) && (dp_accesses == 0.0) && (sfu_accesses == 0.0) && (tensor_accesses == 0.0) && (tex_accesses != 0.0)){ + /* INT_FP_TEX */ + base_static_power = p->sys.static_cat5_flane; + lane_static_power = p->sys.static_cat5_addlane; + } + + else if((int_accesses != 0.0) && (fp_accesses != 0.0) && (dp_accesses == 0.0) && (sfu_accesses == 0.0) && (tensor_accesses == 0.0) && (tex_accesses == 0.0)){ + /* INT_FP */ + base_static_power = p->sys.static_cat2_flane; + lane_static_power = p->sys.static_cat2_addlane; + } + + else if((int_accesses != 0.0) && (fp_accesses == 0.0) && (dp_accesses == 0.0) && (sfu_accesses == 0.0) && (tensor_accesses == 0.0) && (tex_accesses == 0.0)){ + /* INT */ + /* Seperating INT_ADD only and INT_MUL only from mix of INT instructions */ + if((int_add_accesses != 0.0) && (int_mul_accesses == 0.0)){ //INT_ADD + base_static_power = p->sys.static_intadd_flane; + lane_static_power = p->sys.static_intadd_addlane; + } + else if((int_add_accesses == 0.0) && (int_mul_accesses != 0.0)){ //INT_MUL + base_static_power = p->sys.static_intmul_flane; + lane_static_power = p->sys.static_intmul_addlane; + } + else{ //INT_ADD+MUL + base_static_power = p->sys.static_cat1_flane; + lane_static_power = p->sys.static_cat1_addlane; + } + } + + else if((int_accesses == 0.0) && (fp_accesses == 0.0) && (dp_accesses == 0.0) && (sfu_accesses == 0.0) && (tensor_accesses == 0.0) && (tex_accesses == 0.0)){ + /* LIGHT_SM or memory only sample */ + lane_static_power = 0.0; //addlane static power is 0 for l1/l2/shared memory only accesses + if(l1_accesses != 0.0) + base_static_power = p->sys.static_l1_flane; + else if(shared_accesses != 0.0) + base_static_power = p->sys.static_shared_flane; + else if(l2_accesses != 0.0) + base_static_power = p->sys.static_l2_flane; + else{ + base_static_power = p->sys.static_light_flane; + lane_static_power = p->sys.static_light_addlane; + } + } + else{ + base_static_power = p->sys.static_geomean_flane; //GEOMEAN except LIGHT_SM if we don't fall into any of the categories above + lane_static_power = p->sys.static_geomean_addlane; + } + + total_static_power = base_static_power + (((double)avg_threads_per_warp-1.0)*lane_static_power); //Linear Model + return (total_static_power*per_active_core); +} + +void gpgpu_sim_wrapper::update_components_power() +{ + + update_coefficients(); + + proc_power=proc->rt_power.readOp.dynamic; + sample_cmp_pwr[IBP]=(proc->cores[0]->ifu->IB->rt_power.readOp.dynamic + +proc->cores[0]->ifu->IB->rt_power.writeOp.dynamic + +proc->cores[0]->ifu->ID_misc->rt_power.readOp.dynamic + +proc->cores[0]->ifu->ID_operand->rt_power.readOp.dynamic + +proc->cores[0]->ifu->ID_inst->rt_power.readOp.dynamic)/(proc->cores[0]->executionTime); + + sample_cmp_pwr[ICP]=proc->cores[0]->ifu->icache.rt_power.readOp.dynamic/(proc->cores[0]->executionTime); + + sample_cmp_pwr[DCP]=proc->cores[0]->lsu->dcache.rt_power.readOp.dynamic/(proc->cores[0]->executionTime); + + sample_cmp_pwr[TCP]=proc->cores[0]->lsu->tcache.rt_power.readOp.dynamic/(proc->cores[0]->executionTime); + + sample_cmp_pwr[CCP]=proc->cores[0]->lsu->ccache.rt_power.readOp.dynamic/(proc->cores[0]->executionTime); + + sample_cmp_pwr[SHRDP]=proc->cores[0]->lsu->sharedmemory.rt_power.readOp.dynamic/(proc->cores[0]->executionTime); + + sample_cmp_pwr[RFP]=(proc->cores[0]->exu->rfu->rt_power.readOp.dynamic/(proc->cores[0]->executionTime)) + *(proc->cores[0]->exu->rf_fu_clockRate/proc->cores[0]->exu->clockRate); + + double sample_fp_pwr = (proc->cores[0]->exu->fp_u->rt_power.readOp.dynamic/(proc->cores[0]->executionTime)); + + double sample_sfu_pwr = (proc->cores[0]->exu->mul->rt_power.readOp.dynamic/(proc->cores[0]->executionTime)); + + sample_cmp_pwr[INTP]=(proc->cores[0]->exu->exeu->rt_power.readOp.dynamic/(proc->cores[0]->executionTime)) + *(proc->cores[0]->exu->rf_fu_clockRate/proc->cores[0]->exu->clockRate); + + + if(tot_fpu_accesses != 0){ + sample_cmp_pwr[FPUP]= sample_fp_pwr * sample_perf_counters[FP_ACC]/tot_fpu_accesses; + sample_cmp_pwr[DPUP]= sample_fp_pwr * sample_perf_counters[DP_ACC]/tot_fpu_accesses; + } + else{ + sample_cmp_pwr[FPUP]= 0; + sample_cmp_pwr[DPUP]= 0; + } + if(tot_sfu_accesses != 0){ + sample_cmp_pwr[INT_MUL24P]= sample_sfu_pwr * sample_perf_counters[INT_MUL24_ACC]/tot_sfu_accesses; + sample_cmp_pwr[INT_MUL32P]= sample_sfu_pwr * sample_perf_counters[INT_MUL32_ACC]/tot_sfu_accesses; + sample_cmp_pwr[INT_MULP]= sample_sfu_pwr * sample_perf_counters[INT_MUL_ACC]/tot_sfu_accesses; + sample_cmp_pwr[INT_DIVP]= sample_sfu_pwr * sample_perf_counters[INT_DIV_ACC]/tot_sfu_accesses; + sample_cmp_pwr[FP_MULP]= sample_sfu_pwr * sample_perf_counters[FP_MUL_ACC]/tot_sfu_accesses; + sample_cmp_pwr[FP_DIVP]= sample_sfu_pwr * sample_perf_counters[FP_DIV_ACC]/tot_sfu_accesses; + sample_cmp_pwr[FP_SQRTP]= sample_sfu_pwr * sample_perf_counters[FP_SQRT_ACC]/tot_sfu_accesses; + sample_cmp_pwr[FP_LGP]= sample_sfu_pwr * sample_perf_counters[FP_LG_ACC]/tot_sfu_accesses; + sample_cmp_pwr[FP_SINP]= sample_sfu_pwr * sample_perf_counters[FP_SIN_ACC]/tot_sfu_accesses; + sample_cmp_pwr[FP_EXP]= sample_sfu_pwr * sample_perf_counters[FP_EXP_ACC]/tot_sfu_accesses; + sample_cmp_pwr[DP_MULP]= sample_sfu_pwr * sample_perf_counters[DP_MUL_ACC]/tot_sfu_accesses; + sample_cmp_pwr[DP_DIVP]= sample_sfu_pwr * sample_perf_counters[DP_DIV_ACC]/tot_sfu_accesses; + sample_cmp_pwr[TENSORP]= sample_sfu_pwr * sample_perf_counters[TENSOR_ACC]/tot_sfu_accesses; + sample_cmp_pwr[TEXP]= sample_sfu_pwr * sample_perf_counters[TEX_ACC]/tot_sfu_accesses; + } + else{ + sample_cmp_pwr[INT_MUL24P]= 0; + sample_cmp_pwr[INT_MUL32P]= 0; + sample_cmp_pwr[INT_MULP]= 0; + sample_cmp_pwr[INT_DIVP]= 0; + sample_cmp_pwr[FP_MULP]= 0; + sample_cmp_pwr[FP_DIVP]= 0; + sample_cmp_pwr[FP_SQRTP]= 0; + sample_cmp_pwr[FP_LGP]= 0; + sample_cmp_pwr[FP_SINP]= 0; + sample_cmp_pwr[FP_EXP]= 0; + sample_cmp_pwr[DP_MULP]= 0; + sample_cmp_pwr[DP_DIVP]= 0; + sample_cmp_pwr[TENSORP]= 0; + sample_cmp_pwr[TEXP]= 0; + } + + sample_cmp_pwr[SCHEDP]=proc->cores[0]->exu->scheu->rt_power.readOp.dynamic/(proc->cores[0]->executionTime); + + sample_cmp_pwr[L2CP]=(proc->XML->sys.number_of_L2s>0)? proc->l2array[0]->rt_power.readOp.dynamic/(proc->cores[0]->executionTime):0; + + sample_cmp_pwr[MCP]=(proc->mc->rt_power.readOp.dynamic-proc->mc->dram->rt_power.readOp.dynamic)/(proc->cores[0]->executionTime); + + sample_cmp_pwr[NOCP]=proc->nocs[0]->rt_power.readOp.dynamic/(proc->cores[0]->executionTime); + + sample_cmp_pwr[DRAMP]=proc->mc->dram->rt_power.readOp.dynamic/(proc->cores[0]->executionTime); + + sample_cmp_pwr[PIPEP]=proc->cores[0]->Pipeline_energy/(proc->cores[0]->executionTime); + + sample_cmp_pwr[IDLE_COREP]=proc->cores[0]->IdleCoreEnergy/(proc->cores[0]->executionTime); + + // This constant dynamic power (e.g., clock power) part is estimated via regression model. + sample_cmp_pwr[CONSTP]=0; + sample_cmp_pwr[STATICP]=0; + // double cnst_dyn = proc->get_const_dynamic_power()/(proc->cores[0]->executionTime); + // // If the regression scaling term is greater than the recorded constant dynamic power + // // then use the difference (other portion already added to dynamic power). Else, + // // all the constant dynamic power is accounted for, add nothing. + // if(p->sys.scaling_coefficients[constant_power] > cnst_dyn) + // sample_cmp_pwr[CONSTP] = (p->sys.scaling_coefficients[constant_power]-cnst_dyn); + sample_cmp_pwr[CONSTP] = p->sys.scaling_coefficients[constant_power]; + sample_cmp_pwr[STATICP] = calculate_static_power(); + + if(g_dvfs_enabled){ + double voltage_ratio = modeled_chip_voltage/p->sys.modeled_chip_voltage_ref; + sample_cmp_pwr[IDLE_COREP] *= voltage_ratio; // static power scaled by voltage_ratio + sample_cmp_pwr[STATICP] *= voltage_ratio; // static power scaled by voltage_ratio + for(unsigned i=0; i<num_pwr_cmps; i++){ + if((i != IDLE_COREP) && (i != STATICP)){ + sample_cmp_pwr[i] *= voltage_ratio*voltage_ratio; // dynamic power scaled by square of voltage_ratio + } + } + } + + proc_power+=sample_cmp_pwr[CONSTP]+sample_cmp_pwr[STATICP]; + if(!g_dvfs_enabled){ // sanity check will fail when voltage scaling is applied, fix later + double sum_pwr_cmp=0; + for(unsigned i=0; i<num_pwr_cmps; i++){ + sum_pwr_cmp+=sample_cmp_pwr[i]; + } + bool check=false; + check=sanity_check(sum_pwr_cmp,proc_power); + if(!check) + printf("sum_pwr_cmp %f : proc_power %f \n",sum_pwr_cmp,proc_power); + assert("Total Power does not equal the sum of the components\n" && (check)); + } +} + +void gpgpu_sim_wrapper::compute() { proc->compute(); } +void gpgpu_sim_wrapper::print_power_kernel_stats( + double gpu_sim_cycle, double gpu_tot_sim_cycle, double init_value, + const std::string& kernel_info_string, bool print_trace) { + detect_print_steady_state(1, init_value); + if (g_power_simulation_enabled) { + powerfile << kernel_info_string << std::endl; + + sanity_check((kernel_power.avg * kernel_sample_count), kernel_tot_power); + powerfile << "Kernel Average Power Data:" << std::endl; + powerfile << "kernel_avg_power = " << kernel_power.avg << std::endl; + + for (unsigned i = 0; i < num_pwr_cmps; ++i) { + powerfile << "gpu_avg_" << pwr_cmp_label[i] << " = " + << kernel_cmp_pwr[i].avg / kernel_sample_count << std::endl; + } + for (unsigned i = 0; i < num_perf_counters; ++i) { + powerfile << "gpu_avg_" << perf_count_label[i] << " = " + << kernel_cmp_perf_counters[i].avg / kernel_sample_count + << std::endl; + } + + powerfile << "gpu_avg_threads_per_warp = " + << avg_threads_per_warp_tot / (double)kernel_sample_count + << std::endl; + + for (unsigned i = 0; i < num_perf_counters; ++i) { + powerfile << "gpu_tot_" << perf_count_label[i] << " = " + << kernel_cmp_perf_counters[i].avg + << std::endl; + } + + powerfile << std::endl << "Kernel Maximum Power Data:" << std::endl; + powerfile << "kernel_max_power = " << kernel_power.max << std::endl; + for (unsigned i = 0; i < num_pwr_cmps; ++i) { + powerfile << "gpu_max_" << pwr_cmp_label[i] << " = " + << kernel_cmp_pwr[i].max << std::endl; + } + for (unsigned i = 0; i < num_perf_counters; ++i) { + powerfile << "gpu_max_" << perf_count_label[i] << " = " + << kernel_cmp_perf_counters[i].max << std::endl; + } + + powerfile << std::endl << "Kernel Minimum Power Data:" << std::endl; + powerfile << "kernel_min_power = " << kernel_power.min << std::endl; + for (unsigned i = 0; i < num_pwr_cmps; ++i) { + powerfile << "gpu_min_" << pwr_cmp_label[i] << " = " + << kernel_cmp_pwr[i].min << std::endl; + } + for (unsigned i = 0; i < num_perf_counters; ++i) { + powerfile << "gpu_min_" << perf_count_label[i] << " = " + << kernel_cmp_perf_counters[i].min << std::endl; + } + + powerfile << std::endl + << "Accumulative Power Statistics Over Previous Kernels:" + << std::endl; + powerfile << "gpu_tot_avg_power = " + << gpu_tot_power.avg / total_sample_count << std::endl; + powerfile << "gpu_tot_max_power = " << gpu_tot_power.max << std::endl; + powerfile << "gpu_tot_min_power = " << gpu_tot_power.min << std::endl; + powerfile << std::endl << std::endl; + powerfile.flush(); + + if (print_trace) { + print_trace_files(); + } + } +} +void gpgpu_sim_wrapper::dump() { + if (g_power_per_cycle_dump) proc->displayEnergy(2, 5); +} + +void gpgpu_sim_wrapper::print_steady_state(int position, double init_val) { + double temp_avg = sample_val / (double)samples.size(); + double temp_ipc = (init_val - init_inst_val) / + (double)(samples.size() * gpu_stat_sample_freq); + + if ((samples.size() > + gpu_steady_min_period)) { // If steady state occurred for some time, + // print to file + has_written_avg = true; + gzprintf(steady_state_tacking_file, "%u,%d,%f,%f,", sample_start, + total_sample_count, temp_avg, temp_ipc); + for (unsigned i = 0; i < num_perf_counters; ++i) { + gzprintf(steady_state_tacking_file, "%f,", + samples_counter.at(i) / ((double)samples.size())); + } + gzprintf(steady_state_tacking_file, "\n"); + } else { + if (!has_written_avg && position) + gzprintf(steady_state_tacking_file, + "ERROR! Not enough steady state points to generate average\n"); + } + + sample_start = 0; + sample_val = 0; + init_inst_val = init_val; + samples.clear(); + samples_counter.clear(); + pwr_counter.clear(); + assert(samples.size() == 0); +} + +void gpgpu_sim_wrapper::detect_print_steady_state(int position, + double init_val) { + // Calculating Average + if (g_power_simulation_enabled && g_steady_power_levels_enabled) { + steady_state_tacking_file = gzopen(g_steady_state_tracking_filename, "a"); + if (position == 0) { + if (samples.size() == 0) { + // First sample + sample_start = total_sample_count; + sample_val = proc->rt_power.readOp.dynamic; + init_inst_val = init_val; + samples.push_back(proc->rt_power.readOp.dynamic); + assert(samples_counter.size() == 0); + assert(pwr_counter.size() == 0); + + for (unsigned i = 0; i < (num_perf_counters); ++i) { + samples_counter.push_back(sample_perf_counters[i]); + } + + for (unsigned i = 0; i < (num_pwr_cmps); ++i) { + pwr_counter.push_back(sample_cmp_pwr[i]); + } + assert(pwr_counter.size() == (double)num_pwr_cmps); + assert(samples_counter.size() == (double)num_perf_counters); + } else { + // Get current average + double temp_avg = sample_val / (double)samples.size(); + + if (abs(proc->rt_power.readOp.dynamic - temp_avg) < + gpu_steady_power_deviation) { // Value is within threshold + sample_val += proc->rt_power.readOp.dynamic; + samples.push_back(proc->rt_power.readOp.dynamic); + for (unsigned i = 0; i < (num_perf_counters); ++i) { + samples_counter.at(i) += sample_perf_counters[i]; + } + + for (unsigned i = 0; i < (num_pwr_cmps); ++i) { + pwr_counter.at(i) += sample_cmp_pwr[i]; + } + + } else { // Value exceeds threshold, not considered steady state + print_steady_state(position, init_val); + } + } + } else { + print_steady_state(position, init_val); + } + gzclose(steady_state_tacking_file); + } +} + +void gpgpu_sim_wrapper::open_files() { + if (g_power_simulation_enabled) { + if (g_power_trace_enabled) { + power_trace_file = gzopen(g_power_trace_filename, "a"); + metric_trace_file = gzopen(g_metric_trace_filename, "a"); + } + } +} +void gpgpu_sim_wrapper::close_files() { + if (g_power_simulation_enabled) { + if (g_power_trace_enabled) { + gzclose(power_trace_file); + gzclose(metric_trace_file); + } + } +} |
