diff options
author | William Bryan <wilbryan@us.ibm.com> | 2016-04-26 21:20:00 -0500 |
---|---|---|
committer | William A. Bryan <wilbryan@us.ibm.com> | 2016-08-26 16:44:47 -0400 |
commit | c184079818cd001b5fd7664ca974ee721c576522 (patch) | |
tree | ac70f716a10c24d6ef63b7d9b4a46af8b1fe74cc /src/occ_405/amec/amec_sensors_core.c | |
parent | 9600645dd82bfde4f5bc71ddc578bdab914efa14 (diff) | |
download | talos-occ-c184079818cd001b5fd7664ca974ee721c576522.tar.gz talos-occ-c184079818cd001b5fd7664ca974ee721c576522.zip |
EMPATH Sensor Counters
RTC:148388
Change-Id: Iae66cd0a73032fa908eb96a149d4163397c2e275
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/27781
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Reviewed-by: Wael El-Essawy <welessa@us.ibm.com>
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Diffstat (limited to 'src/occ_405/amec/amec_sensors_core.c')
-rwxr-xr-x | src/occ_405/amec/amec_sensors_core.c | 383 |
1 files changed, 157 insertions, 226 deletions
diff --git a/src/occ_405/amec/amec_sensors_core.c b/src/occ_405/amec/amec_sensors_core.c index d330898..ff4f81e 100755 --- a/src/occ_405/amec/amec_sensors_core.c +++ b/src/occ_405/amec/amec_sensors_core.c @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/amec/amec_sensors_core.c $ */ +/* $Source: src/occ_405/amec/amec_sensors_core.c $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -56,11 +56,10 @@ extern data_cnfg_t * G_data_cnfg; void amec_calc_dts_sensors(CoreData * i_core_data_ptr, uint8_t i_core); void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core); void amec_calc_ips_sensors(CoreData * i_core_data_ptr, uint8_t i_core); -void amec_calc_spurr(uint8_t i_core); -//************************************************************************* +//*************************************************************************/ // Code -//************************************************************************* +//*************************************************************************/ // Function Specification // @@ -73,9 +72,10 @@ void amec_calc_spurr(uint8_t i_core); // End Function Specification void amec_update_proc_core_sensors(uint8_t i_core) { - CoreData *l_core_data_ptr; - uint16_t l_temp16 = 0; - uint32_t l_temp32 = 0; + CoreData *l_core_data_ptr; + uint16_t l_temp16 = 0; + uint32_t l_temp32 = 0; + uint8_t i = 0; // Make sure the core is present, and that it has updated data. if(CORE_PRESENT(i_core) && CORE_UPDATED(i_core)) @@ -91,8 +91,6 @@ void amec_update_proc_core_sensors(uint8_t i_core) //------------------------------------------------------- amec_calc_dts_sensors(l_core_data_ptr, i_core); -// @TODO - TEMP: frequency and utilization sensors are not enabled yet. -/* //------------------------------------------------------- // Util / Freq //------------------------------------------------------- @@ -106,7 +104,7 @@ void amec_update_proc_core_sensors(uint8_t i_core) // Performance counter - This function should be called // after amec_calc_freq_and_util_sensors(). //------------------------------------------------------- - //amec_calc_dps_util_counters(i_core); + amec_calc_dps_util_counters(i_core); //------------------------------------------------------- // IPS @@ -117,33 +115,35 @@ void amec_update_proc_core_sensors(uint8_t i_core) amec_calc_ips_sensors(l_core_data_ptr,i_core); } - //------------------------------------------------------- - // SPURR - //------------------------------------------------------- - //amec_calc_spurr(i_core); - // ------------------------------------------------------ // Update PREVIOUS values for next time // ------------------------------------------------------ - g_amec->proc[0].core[i_core].prev_PC_RAW_Th_CYCLES = l_core_data_ptr->per_thread[0].raw_cycles; + + // Thread raw cycles are equivalent to core raw cycles. + g_amec->proc[0].core[i_core].prev_PC_RAW_Th_CYCLES = l_core_data_ptr->empath.raw_cycles; // Skip empath updates if there was an empath collection error on this core if (!CORE_EMPATH_ERROR(i_core)) { g_amec->proc[0].core[i_core].prev_PC_RAW_CYCLES = l_core_data_ptr->empath.raw_cycles; g_amec->proc[0].core[i_core].prev_PC_RUN_CYCLES = l_core_data_ptr->empath.run_cycles; - g_amec->proc[0].core[i_core].prev_PC_COMPLETED = l_core_data_ptr->empath.completion; - g_amec->proc[0].core[i_core].prev_PC_DISPATCH = l_core_data_ptr->empath.dispatch; g_amec->proc[0].core[i_core].prev_tod_2mhz = l_core_data_ptr->empath.tod_2mhz; g_amec->proc[0].core[i_core].prev_FREQ_SENS_BUSY = l_core_data_ptr->empath.freq_sens_busy; g_amec->proc[0].core[i_core].prev_FREQ_SENS_FINISH = l_core_data_ptr->empath.freq_sens_finish; } + // Need to sum up all thread data for full core data + g_amec->proc[0].core[i_core].prev_PC_COMPLETED = 0; + g_amec->proc[0].core[i_core].prev_PC_DISPATCH = 0; for(i=0; i<MAX_THREADS_PER_CORE; i++) { - g_amec->proc[0].core[i_core].thread[i].prev_PC_RUN_Th_CYCLES = l_core_data_ptr->per_thread[i].run_cycles; + g_amec->proc[0].core[i_core].prev_PC_COMPLETED += + l_core_data_ptr->per_thread[i].completion; + g_amec->proc[0].core[i_core].prev_PC_DISPATCH += + l_core_data_ptr->per_thread[i].dispatch; + g_amec->proc[0].core[i_core].thread[i].prev_PC_RUN_Th_CYCLES = l_core_data_ptr->per_thread[i].run_cycles; } -*/ + // Final step is to update TOD sensors // Extract 32 bits with 16usec resolution l_temp32 = (uint32_t)(G_dcom_slv_inbox_doorbell_rx.tod>>13); @@ -164,7 +164,7 @@ void amec_update_proc_core_sensors(uint8_t i_core) // Name: amec_calc_dts_sensors // // Description: Compute core temperature. This function is called every -// 2ms/core. +// 4ms/core. // // PreCondition: The core is present. // @@ -312,17 +312,15 @@ void amec_calc_dts_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // Name: amec_calc_freq_and_util_sensors // // Description: Compute the frequency and utilization sensors for a given core. -// This function is called every 2ms/core. +// This function is called every 4ms/core. // // Thread: RealTime Loop // // End Function Specification -// TEMP - Not supported yet. -#if 0 void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) { BOOLEAN l_core_sleep_winkle = FALSE; - uint32_t l_pm_state_hist_reg = 0; + uint32_t l_stop_state_hist_reg = 0; uint32_t temp32 = 0; uint32_t temp32a = 0; uint16_t temp16 = 0; @@ -330,15 +328,15 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) uint16_t l_core_util = 0; uint16_t l_core_freq = 0; uint16_t l_time_interval = 0; - uint32_t l_cycles2ms = 0; + uint32_t l_cycles4ms = 0; int i; - // Read the high-order bytes of PM State History register for this core - l_pm_state_hist_reg = i_core_data_ptr->pcb_slave.pm_history.words.high_order; + // Read the high-order bytes of OCC Stop State History Register + l_stop_state_hist_reg = (uint32_t) (i_core_data_ptr->stop_state_hist >> 32); // If core is in fast/deep sleep mode or fast/winkle mode, then set a flag // indicating this - if(l_pm_state_hist_reg & OCC_PAST_CORE_CLK_STOP) + if(l_stop_state_hist_reg & OCC_CORE_STOP_GATED) { l_core_sleep_winkle = TRUE; } @@ -348,36 +346,30 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // ------------------------------------------------------ // <amec_formula> // Result: Calculated Core Frequency - // Sensor: FREQA2MSP0C0 - // Timescale: 2ms + // Sensor: FREQA4MSP0C0 + // Timescale: 4ms // Units: MHz // Min/Max: 0/6000 (UPPER_LIMIT_PROC_FREQ_MHZ=6000) - // Formula: cyc_delta = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-2ms]) - // time_delta = (TOD[t=now] - TOD[t=-2ms]) + // Formula: cyc_delta(cycles) = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-4ms]) + // time_delta(TOD ticks) = (TOD[t=now] - TOD[t=-4ms]) // frequency(MHz) = (cyc_delta / time_delta) * (2M TOD ticks / 1 second) // = (2 * cyc_delta) / time_delta + // NOTE: cyc_delta is the total number of cycles in 4ms time for the core + // NOTE: In the HWP where we aquire the TOD count, we shift the counter by 8 + // which causes each TOD tick here to equate to 0.5us. This is why we + // are multiplying by 2 in the above equation. // </amec_formula> // Compute Delta in PC_RAW_CYCLES temp32 = i_core_data_ptr->empath.raw_cycles; temp32a = g_amec->proc[0].core[i_core].prev_PC_RAW_CYCLES; - temp32 = l_cycles2ms = temp32 - temp32a; + temp32 = l_cycles4ms = temp32 - temp32a; + temp32a = (i_core_data_ptr->empath.tod_2mhz - + g_amec->proc[0].core[i_core].prev_tod_2mhz); - if( (cfam_id() == CFAM_CHIP_ID_MURANO_10) - || (cfam_id() == CFAM_CHIP_ID_MURANO_11) - || (cfam_id() == CFAM_CHIP_ID_MURANO_12) ) - { - temp32a = AMEC_US_PER_SMH_PERIOD; // using fixed 2000us is showing 3% error. - temp32 = temp32 / temp32a; - } - else - { - temp32a = (i_core_data_ptr->empath.tod_2mhz - - g_amec->proc[0].core[i_core].prev_tod_2mhz); - temp32 = (2 * temp32) / temp32a; - } + if (0 == temp32a) temp32 = 0; + else temp32 = (2 * temp32) / temp32a; - // TODO: Remove this once we have the OHA Power Proxy legacy mode stuff working. if(temp32 < UPPER_LIMIT_PROC_FREQ_MHZ) { // Update Sensor for this core @@ -389,7 +381,7 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) { l_core_freq = (uint16_t) temp32; } - sensor_update( AMECSENSOR_ARRAY_PTR(FREQA2MSP0C0,i_core), l_core_freq); + sensor_update( AMECSENSOR_ARRAY_PTR(FREQA4MSP0C0,i_core), l_core_freq); } // ------------------------------------------------------ @@ -397,14 +389,16 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // ------------------------------------------------------ // <amec_formula> // Result: Calculated Core Utilization - // Sensor: UTIL2MSP0C0 - // Timescale: 2ms + // Sensor: UTIL4MSP0C0 + // Timescale: 4ms // Units: 0.01 % // Min/Max: 0/10000 (0/100%) - // Formula: cyc_delta = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-2ms]) - // run_delta = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-2ms]) - // + // Formula: cyc_delta = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-4ms]) + // run_delta = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-4ms]) // UTIL(in %) = run_delta / cyc_delta + // + // NOTE: cyc_delta is the total number of cycles in 4ms time for the core + // NOTE: run_delta is the total number of cycles utilized by a specific core in 4ms // </amec_formula> // Compute Delta in PC_RUN_CYCLES @@ -417,15 +411,12 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) temp16a = 10000; // Mult * 10000 to get finer resolution for 0.01% temp32 = ((uint32_t)temp16a)*((uint32_t)temp16); - temp32a = l_cycles2ms; // Get Raw cycles + temp32a = l_cycles4ms; // Get Raw cycles temp32a = temp32a >> 8; // Drop non-significant bits // Calculate Utilization - temp32 = temp32 / temp32a; - if(temp32a == 0) // Prevent a divide by zero - { - temp32 = 0; - } + if(0 == temp32a) temp32 = 0; // Prevent a divide by zero + else temp32 = temp32 / temp32a; // Update Sensor for this core if(l_core_sleep_winkle) @@ -436,8 +427,7 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) { l_core_util = (uint16_t) temp32; } - sensor_update(AMECSENSOR_ARRAY_PTR(UTIL2MSP0C0, i_core), l_core_util); - + sensor_update(AMECSENSOR_ARRAY_PTR(UTIL4MSP0C0, i_core), l_core_util); // ------------------------------------------------------ // Per Thread Utilization @@ -445,19 +435,22 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // <amec_formula> // Result: Calculated Core Utilization // Sensor: None - // Timescale: 2ms + // Timescale: 4ms // Units: 0.01 % // Min/Max: 0/10000 (0/100%) - // Formula: cyc_delta = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-2ms]) - // run_delta = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-2ms]) - // + // Formula: cyc_delta = (RAW_CYCLES[t=now] - RAW_CYCLES[t=-4ms]) + // run_delta = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-4ms]) // UTIL(in %) = run_delta / cyc_delta + // + // NOTE: cyc_delta is the total number of cycles run by the core in 4ms + // NOTE: run_delta is the total number of cycles run by a specific thread in 4ms // </amec_formula> // Get RAW CYCLES for Thread - temp32 = i_core_data_ptr->per_thread[0].raw_cycles; + // Thread raw cycles are the same as core raw cycles + temp32 = i_core_data_ptr->empath.raw_cycles; temp32a = g_amec->proc[0].core[i_core].prev_PC_RAW_Th_CYCLES; - temp32 = l_cycles2ms = temp32 - temp32a; + l_cycles4ms = temp32 - temp32a; for(i=0; i<MAX_THREADS_PER_CORE; i++) { @@ -471,18 +464,19 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) temp16a = 10000; // Mult * 10000 to get finer resolution for 0.01% temp32 = ((uint32_t)temp16a)*((uint32_t)temp16); - temp32a = l_cycles2ms; + temp32a = l_cycles4ms; temp32a = temp32a >> 8; // Drop non-significant bits // Calculate Utilization - temp32 = temp32 / temp32a; + if (0 == temp32a) temp32 = 0; // Prevent divide by 0 + else temp32 = temp32 / temp32a; // Update per thread value for this core if(l_core_sleep_winkle) { temp32 = 0; } - g_amec->proc[0].core[i_core].thread[i].util2ms_thread = (uint16_t) temp32; + g_amec->proc[0].core[i_core].thread[i].util4ms_thread = (uint16_t) temp32; } // No sensors to update for perThread Util @@ -491,59 +485,38 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // Per Core Sleep/Winkle Count // ------------------------------------------------------ - // Get Current Idle State of Chiplet + // Get deepest idle state entered by the chiplet since the last read + // The SLEEPCNT and WINKLECNT sensors are updated in amec_slv_state_0() function - temp16 = CONVERT_UINT64_UINT16_UPPER(i_core_data_ptr->pcb_slave.pm_history.value); - temp16 = temp16 & 0xE000; - temp16 = temp16 >> 13; + temp16 = CONVERT_UINT64_UINT16_MIDUPPER(i_core_data_ptr->stop_state_hist); + temp16 = temp16 & 0xF000; + temp16 = temp16 >> 12; switch(temp16) { - case 0: break; // Run State - case 1: break; // Special Wakeup - case 2: break; // Nap - case 3: SETBIT(g_amec->proc[0].sleep_cnt,i_core); break; // Legacy Sleep - case 4: SETBIT(g_amec->proc[0].sleep_cnt,i_core); break; // Fast Sleep - case 5: SETBIT(g_amec->proc[0].sleep_cnt,i_core); break; // Deep Sleep - case 6: SETBIT(g_amec->proc[0].winkle_cnt,i_core); break; // Fast Winkle - case 7: SETBIT(g_amec->proc[0].winkle_cnt,i_core); break; // Deep Winkle + case 0: // Stop 0: Run State + case 1: // Stop 1: Nap + break; + case 2: // Stop 2: Fast Sleep + case 3: // Stop 3: Fast Sleep @ Vmin + case 4: // Stop 4: Deep Sleep "instant on" + case 5: // Stop 5-7: Higher Latency Deep Sleep + case 6: + case 7: + case 8: // Stop 8-10: Deep Sleep+ + case 9: + case 10: + SETBIT(g_amec->proc[0].sleep_cnt,i_core); + break; + case 11: // Stop 11-15: Quad Deep Winkle + case 12: + case 13: + case 14: + case 15: + SETBIT(g_amec->proc[0].winkle_cnt,i_core); + break; } // ------------------------------------------------------ - // Core Memory Hierarchy C LPARx Utilization counters - // ------------------------------------------------------ - for(i=0; i<4; i++) - { - // Extract the utilization counter - temp32 = i_core_data_ptr->per_partition_memory.count[i]; - - // Convert counter to 0.01 Mrps resolution. Since we access every 2 ms: - // ((2ms read * 500) / 10000) - temp32a = temp32 - g_amec->proc[0].core[i_core].prev_lpar_mem_cnt[i]; - g_amec->proc[0].core[i_core].prev_lpar_mem_cnt[i] = temp32; - temp32 = (temp32a * 5) / 100; - - // Store the bandwidth for this LPAR - g_amec->proc[0].core[i_core].membw[i] = (uint16_t)temp32; - } - - // Sum up all the memory bandwidth data from the LPARs - temp32 = g_amec->proc[0].core[i_core].membw[0] + - g_amec->proc[0].core[i_core].membw[1] + - g_amec->proc[0].core[i_core].membw[2] + - g_amec->proc[0].core[i_core].membw[3]; - - // Divide by two due to a bug in the hardware - temp32 = temp32/2; - - // See if core is sleeping/winkled - if(l_core_sleep_winkle) - { - temp32 = 0; - } - // Update Sensor for this core - sensor_update( AMECSENSOR_ARRAY_PTR(CMBW2MSP0C0,i_core), (uint16_t) temp32); - - // ------------------------------------------------------ // Core Stall counters // ------------------------------------------------------ temp32 = i_core_data_ptr->empath.freq_sens_busy; @@ -553,12 +526,12 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // See if core is sleeping/winkled if(l_core_sleep_winkle) - { - temp32 = 0; - } + { + temp32 = 0; + } // Update Sensor for this core - sensor_update( AMECSENSOR_ARRAY_PTR(NOTBZE2MSP0C0,i_core), (uint16_t) temp32); + sensor_update( AMECSENSOR_ARRAY_PTR(NOTBZE4MSP0C0,i_core), (uint16_t) temp32); temp32 = i_core_data_ptr->empath.freq_sens_finish; temp32a = g_amec->proc[0].core[i_core].prev_FREQ_SENS_FINISH; @@ -567,12 +540,12 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // See if core is sleeping/winkled if(l_core_sleep_winkle) - { - temp32 = 0; - } + { + temp32 = 0; + } // Update Sensor for this core - sensor_update( AMECSENSOR_ARRAY_PTR(NOTFIN2MSP0C0,i_core), (uint16_t) temp32); + sensor_update( AMECSENSOR_ARRAY_PTR(NOTFIN4MSP0C0,i_core), (uint16_t) temp32); // ------------------------------------------------------ // Per Core Normalized Average Utilization @@ -580,7 +553,7 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // <amec_formula> // Result: Calculated Normalized Average Core Utilization // Sensor: NUTIL3SP0C0 - // Timescale: 2ms (3s rolling average) + // Timescale: 4ms (3s rolling average) // Units: 0.01 % // Min/Max: 0/10000 (0/100%) // </amec_formula> @@ -597,13 +570,13 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) if(g_amec->proc[0].core[i_core].sample_count == l_time_interval) { // Increase resolution of the UTIL accumulator by two decimal places - temp32 = (uint32_t)AMECSENSOR_ARRAY_PTR(UTIL2MSP0C0,i_core)->accumulator * 100; + temp32 = (uint32_t)AMECSENSOR_ARRAY_PTR(UTIL4MSP0C0,i_core)->accumulator * 100; // Calculate average utilization of this core temp32 = temp32 / g_amec->proc[0].core[i_core].sample_count; g_amec->proc[0].core[i_core].avg_util = temp32; // Increase resolution of the FREQA accumulator by two decimal places - temp32 = (uint32_t)AMECSENSOR_ARRAY_PTR(FREQA2MSP0C0,i_core)->accumulator * 100; + temp32 = (uint32_t)AMECSENSOR_ARRAY_PTR(FREQA4MSP0C0,i_core)->accumulator * 100; // Calculate average frequency of this core temp32 = temp32 / g_amec->proc[0].core[i_core].sample_count; g_amec->proc[0].core[i_core].avg_freq = temp32; @@ -617,12 +590,6 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) temp32 = temp32 + l_core_util*100; g_amec->proc[0].core[i_core].avg_util = temp32 / l_time_interval; - // Could be needed for increase accuracy - //if(g_amec->proc[0].core[i_core].avg_util > 9000) - //{ This rounds up only! - //g_amec->proc[0].core[i_core].avg_util = (temp32+ (1500-1)) / 1500; - //} - // Calculate average frequency for this core temp32 = (uint32_t) g_amec->proc[0].core[i_core].avg_freq; temp32 = temp32 * (l_time_interval-1); @@ -655,7 +622,6 @@ void amec_calc_freq_and_util_sensors(CoreData * i_core_data_ptr, uint8_t i_core) } } - void amec_calc_ips_sensors(CoreData * i_core_data_ptr, uint8_t i_core) { #define TWO_PWR_24_MASK 0x00FFFFFF @@ -673,15 +639,15 @@ void amec_calc_ips_sensors(CoreData * i_core_data_ptr, uint8_t i_core) UINT32 temp32 = 0; UINT32 ticks_2mhz = 0; // IPS sensor interval in 2mhz ticks BOOLEAN l_core_sleep_winkle = FALSE; - uint32_t l_pm_state_hist_reg = 0; + uint32_t l_stop_state_hist_reg = 0; + uint8_t thread = 0; - - // Read the high-order bytes of PM State History register for this core - l_pm_state_hist_reg = i_core_data_ptr->pcb_slave.pm_history.words.high_order; + // Read the high-order bytes of OCC Stop State History Register + l_stop_state_hist_reg = (uint32_t) (i_core_data_ptr->stop_state_hist >> 32); // If core is in fast/deep sleep mode or fast/winkle mode, then set a flag // indicating this - if(l_pm_state_hist_reg & OCC_PAST_CORE_CLK_STOP) + if(l_stop_state_hist_reg & OCC_CORE_STOP_GATED) { l_core_sleep_winkle = TRUE; } @@ -690,58 +656,45 @@ void amec_calc_ips_sensors(CoreData * i_core_data_ptr, uint8_t i_core) /* Code */ /*------------------------------------------------------------------------*/ - // Get Run Cycles + // Get current and last run Cycles cyc1 = i_core_data_ptr->empath.run_cycles; cyc2 = g_amec->proc[0].core[i_core].prev_PC_RUN_CYCLES; cyc2 = cyc1 - cyc2; - // Following lines look bogus...the counters are supposed to be 32-bit - // since we are doing 24-bit unsigned math, we need to account for the - // overflow case. If this occurs, we mask off the "overflow" to make it behave - // like a 32-bit subtraction overflow would. Commenting them out. - //if ( cyc2 < 0 ) - //{ - // cyc2 &= TWO_PWR_24_MASK; - //} + // Calculate core completion and dispatch (sum of all threads) + for ( thread = 0; thread < MAX_THREADS_PER_CORE; thread++ ) + { + fin1 += i_core_data_ptr->per_thread[thread].completion; + disp1 += i_core_data_ptr->per_thread[thread].dispatch; + } - fin1 = i_core_data_ptr->empath.completion; + // Calculate delta of completed instructions fin2 = g_amec->proc[0].core[i_core].prev_PC_COMPLETED; fin2 = fin1 - fin2; - // Is this counting every completed instruction or 1 of every 16? - // Why are we masking 20 bits of a 32-bit counter? Commenting these lines out. - //if ( fin2 < 0 ) - //{ - // fin2 &= TWO_PWR_20_MASK; - //} - - disp1 = i_core_data_ptr->empath.dispatch; + // Calculate delta of dispatched instructions disp2 = g_amec->proc[0].core[i_core].prev_PC_DISPATCH; disp2 = disp1 - disp2; - if ( disp2 < 0 ) - { - disp2 &= TWO_PWR_20_MASK; - } - // ------------------------------------------------------ // Per Core IPC Calculation // ------------------------------------------------------ // <amec_formula> // Result: Calculated Instructions per Cycle // Sensor: None - // Timescale: 2ms + // Timescale: 4ms // Units: 0.01 IPC // Min/Max: ? - // Formula: ipc_delta = (INST_COMPLETE[t=now] - INST_COMPLETE[t=-2ms]) - // run_cycles = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-2ms]) - // 100 = Convert 0.01 DPC + // Formula: ipc_delta = (INST_COMPLETE[t=now] - INST_COMPLETE[t=-4ms]) + // run_cycles = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-4ms]) + // 100 = Convert 0.01 IPC // // IPC(in 0.01 IPC) = (ipc_delta * 100) / run_cycles // </amec_formula> - temp32 = (fin2 * 100); // In units of IPS - temp32 = temp32 / cyc2; // In units of 0.01 DPC - g_amec->proc[0].core[i_core].ipc = temp32; + temp32 = (fin2 * 100); // Number of instructions completed (x100) + if (0 == cyc2) temp32 = 0; // Prevent divide by zero + else temp32 = temp32 / cyc2; // In units of 0.01 IPC + g_amec->proc[0].core[i_core].ipc = temp32; // Currently unused // ------------------------------------------------------ @@ -750,18 +703,19 @@ void amec_calc_ips_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // <amec_formula> // Result: Calculated dispatched Instructions per Cycle // Sensor: None - // Timescale: 2ms - // Units: 0.2Mips + // Timescale: 4ms + // Units: 0.01 DPC // Min/Max: ? - // Formula: dpc_delta = (INST_DISPATCH[t=now] - INST_DISPATCH[t=-2ms]) - // run_cycles = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-2ms]) - // 100 = Convert 0.01 DPC + // Formula: dpc_delta = (INST_DISPATCH[t=now] - INST_DISPATCH[t=-4ms]) + // run_cycles = (RUN_CYCLES[t=now] - RUN_CYCLES[t=-4ms]) + // 100 = Convert 0.01 DPC // // DPC(in 0.01DPC) = (dpc_delta * 100) / run_cycles // </amec_formula> - temp32 = (disp2 * 100); // In units of IPS - temp32 = temp32 / cyc2; // In units of 0.01 DPC - g_amec->proc[0].core[i_core].dpc = temp32; + temp32 = (disp2 * 100); // Number of instructions dispatched (x100) + if (0 == cyc2) temp32 = 0; // Prevent divide by zero + else temp32 = temp32 / cyc2; // In units of 0.01 DPC + g_amec->proc[0].core[i_core].dpc = temp32; // Currently unused // ------------------------------------------------------ // Per Core DPS Calculation @@ -769,75 +723,52 @@ void amec_calc_ips_sensors(CoreData * i_core_data_ptr, uint8_t i_core) // <amec_formula> // Result: Calculated dispatched Instructions per Second // Sensor: None - // Timescale: 2ms + // Timescale: 4ms // Units: 0.2Mips // Min/Max: ? - // Formula: dps_delta = (INST_DISPATCH[t=now] - INST_DISPATCH[t=-2ms]) - // 500 = # of 2ms periods in 1 second - // 50,000 = Convert IPS to 0.2MIPS + // Formula: dps_delta = (INST_DISPATCH[t=now] - INST_DISPATCH[t=-4ms]) + // 250 = # of 4ms periods in 1 second + // 50,000 = Convert IPS to 0.2MIPS // - // DPS(in 0.2Mips) = (dps_delta * 500) / 50,000 + // DPS(in 0.2Mips) = (dps_delta * 250) / 50,000 // </amec_formula> - temp32 = (disp2 * AMEC_SMH_PERIODS_IN_1SEC); // In untis of IPS - temp32 = temp32 / 50000; // In units of 0.2Mips (max 327675 Mips for uint16_t) - g_amec->proc[0].core[i_core].dps = temp32; + + temp32 = (disp2 * AMEC_CORE_COLLECTION_1SEC); // Number of instructions dispatched extrapolated to 1s. + temp32 = temp32 / 50000; // In units of 0.2Mips (max 327675 Mips for uint16_t) + g_amec->proc[0].core[i_core].dps = temp32; // Currently unused // ------------------------------------------------------ // Per Core IPS Calculation // ------------------------------------------------------ // <amec_formula> // Result: Calculated Instructions per Second - // Sensor: IPS2MSP0C0 - // Timescale: 2ms + // Sensor: IPS4MSP0C0 + // Timescale: 4ms // Units: 0.2Mips // Min/Max: ? // Formula: - // comp_delta = (INST_COMPLETE[t=now] - INST_COMPLETE[t=-2ms]) - // ticks_delta = (TOD[t=now] - TOD[t=-2ms]) + // comp_delta = (INST_COMPLETE[t=now] - INST_COMPLETE[t=-4ms]) + // ticks_delta = (TOD[t=now] - TOD[t=-4ms]) // MIPS = comp_delta (insns/interval) * (1 interval per ticks_delta 2mhz ticks) * (2M 2mhz ticks / s) / 1M // = (2* fin2) / ticks_2mhz + // // Note: For best resolution do multiply first and division last. + // Note: For an explanation regarding the multiply by 2, see the note under FREQA4MSP0C0. // </amec_formula> ticks_2mhz = i_core_data_ptr->empath.tod_2mhz - g_amec->proc[0].core[i_core].prev_tod_2mhz; - temp32 = (fin2 << 1) / ticks_2mhz; - // See if core is sleeping/winkled - if(l_core_sleep_winkle) - { - temp32 = 0; - } - sensor_update( AMECSENSOR_ARRAY_PTR(IPS2MSP0C0,i_core), (uint16_t) temp32); -} - - -// Function Specification -// -// Name: amec_calc_spurr -// -// Description: Do SPURR calculation. Must run after FreqA is calculated. -// -// Thread: RealTime Loop -// -// End Function Specification -void amec_calc_spurr(uint8_t i_core) -{ - uint16_t l_actual_freq = AMECSENSOR_ARRAY_PTR(FREQA2MSP0C0, i_core)->sample; - uint16_t l_nominal = 2790; - uint32_t temp32; - - // Sanity Check on Freq - if(l_actual_freq < UPPER_LIMIT_PROC_FREQ_MHZ) - { - temp32 = ((uint32_t) (l_actual_freq * 1000) / l_nominal); - // Scale for SPURR Register (64 = Nominal, 32 = Nom-50%) - temp32 = (temp32 * 64) / 1000; + if (0 == ticks_2mhz) temp32 = 0; + else temp32 = (fin2 << 1) / ticks_2mhz; - sensor_update( AMECSENSOR_ARRAY_PTR(SPURR2MSP0C0,i_core), (uint16_t) temp32); - } + // See if core is sleeping/winkled + if(l_core_sleep_winkle) + { + temp32 = 0; + } + sensor_update( AMECSENSOR_ARRAY_PTR(IPS4MSP0C0,i_core), (uint16_t) temp32); } -#endif /*----------------------------------------------------------------------------*/ /* End */ |