diff options
-rwxr-xr-x | src/occ_405/amec/amec_parm.h | 13 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_parm_table.c | 14 | ||||
-rwxr-xr-x | src/occ_405/main.c | 6 | ||||
-rw-r--r-- | src/occ_405/occ_service_codes.h | 3 | ||||
-rw-r--r-- | src/occ_405/wof/wof.c | 202 | ||||
-rw-r--r-- | src/occ_405/wof/wof.h | 35 | ||||
-rw-r--r-- | src/occ_405/wof/wof_service_codes.h | 4 |
7 files changed, 272 insertions, 5 deletions
diff --git a/src/occ_405/amec/amec_parm.h b/src/occ_405/amec/amec_parm.h index 7a0cd30..9223f83 100755 --- a/src/occ_405/amec/amec_parm.h +++ b/src/occ_405/amec/amec_parm.h @@ -78,6 +78,7 @@ typedef enum PARM_TEMPPROCTHERMC, PARM_TEMPNEST, PARM_TEMPQ, + PARM_VOLTVDN, PARM_QUAD_X_PSTATES, PARM_IVRM_STATES, PARM_IDC_VDD, @@ -85,7 +86,19 @@ typedef enum PARM_IDC_QUAD, PARM_IAC_VDD, PARM_IAC_VDN, + PARM_IAC_TDP_VDD, + PARM_IAC_TDP_VDN, PARM_VOLTAGE_IDX, + PARM_V_RATIO, + PARM_F_RATIO, + PARM_V_CLIP, + PARM_F_CLIP, + PARM_CEFF_TDP_VDD, + PARM_CEFF_VDD, + PARM_CEFF_RATIO_VDD, + PARM_CEFF_TDP_VDN, + PARM_CEFF_VDN, + PARM_CEFF_RATIO_VDN, PARM_ALL_CORES_OFF_ISO, PARM_ALL_CACHES_ON_ISO, PARM_QUAD_GOOD_CORES_ONLY, diff --git a/src/occ_405/amec/amec_parm_table.c b/src/occ_405/amec/amec_parm_table.c index 01baaff..e1ef156 100755 --- a/src/occ_405/amec/amec_parm_table.c +++ b/src/occ_405/amec/amec_parm_table.c @@ -150,6 +150,7 @@ amec_parm_t g_amec_parm_list[] = { AMEC_PARM_UINT16_ARRAY(PARM_TEMPPROCTHERMC, "tempprocthrmc", &g_amec_sys.wof.tempprocthrmc, MAX_NUM_CORES), AMEC_PARM_UINT16(PARM_TEMPNEST, "tempnest_sensor", &g_amec_sys.wof.tempnest_sensor), AMEC_PARM_UINT16_ARRAY(PARM_TEMPQ, "tempq", &g_amec_sys.wof.tempq, MAX_NUM_QUADS), + AMEC_PARM_UINT16(PARM_VOLTVDN, "voltvdn_sensor", &g_amec_sys.wof.voltvdn_sensor), AMEC_PARM_UINT8_ARRAY(PARM_QUAD_X_PSTATES, "quad_x_pstates", &g_amec_sys.wof.quad_x_pstates, MAX_NUM_QUADS), AMEC_PARM_UINT8(PARM_IVRM_STATES, "quad_ivrm_states", &g_amec_sys.wof.quad_ivrm_states), AMEC_PARM_UINT32(PARM_IDC_VDD, "idc_vdd", &g_amec_sys.wof.idc_vdd), @@ -157,6 +158,19 @@ amec_parm_t g_amec_parm_list[] = { AMEC_PARM_UINT32(PARM_IDC_QUAD, "idc_quad", &g_amec_sys.wof.idc_quad), AMEC_PARM_UINT32(PARM_IAC_VDD, "iac_vdd", &g_amec_sys.wof.iac_vdd), AMEC_PARM_UINT32(PARM_IAC_VDN, "iac_vdn", &g_amec_sys.wof.iac_vdn), + AMEC_PARM_UINT32(PARM_IAC_TDP_VDD, "iac_tdp_vdd", &g_amec_sys.wof.iac_tdp_vdd), + AMEC_PARM_UINT32(PARM_IAC_TDP_VDN, "iac_tdp_vdn", &g_amec_sys.wof.iac_tdp_vdn), + AMEC_PARM_UINT32(PARM_V_RATIO, "Vratio", &g_amec_sys.wof.v_ratio), + AMEC_PARM_UINT32(PARM_F_RATIO, "Fratio", &g_amec_sys.wof.f_ratio), + AMEC_PARM_UINT32(PARM_V_CLIP, "Vclip", &g_amec_sys.wof.v_clip), + AMEC_PARM_UINT32(PARM_F_CLIP, "Fclip", &g_amec_sys.wof.f_clip), + AMEC_PARM_UINT32(PARM_CEFF_TDP_VDD, "ceff_tdp_vdd", &g_amec_sys.wof.ceff_tdp_vdd), + AMEC_PARM_UINT32(PARM_CEFF_VDD, "ceff_vdd", &g_amec_sys.wof.ceff_vdd), + AMEC_PARM_UINT32(PARM_CEFF_RATIO_VDD, "ceff_ratio_vdd", &g_amec_sys.wof.ceff_ratio_vdd), + AMEC_PARM_UINT32(PARM_CEFF_TDP_VDN, "ceff_tdp_vdn", &g_amec_sys.wof.ceff_tdp_vdn), + AMEC_PARM_UINT32(PARM_CEFF_VDN, "ceff_vdn", &g_amec_sys.wof.ceff_vdn), + AMEC_PARM_UINT32(PARM_CEFF_RATIO_VDN, "ceff_ratio_vdn", &g_amec_sys.wof.ceff_ratio_vdn), + AMEC_PARM_UINT8(PARM_VOLTAGE_IDX, "voltage_idx", &g_amec_sys.wof.voltage_idx), AMEC_PARM_UINT32(PARM_ALL_CORES_OFF_ISO, "allcores_off_iso", &g_amec_sys.wof.all_cores_off_iso), AMEC_PARM_UINT32(PARM_ALL_CACHES_ON_ISO, "allcaches_on_iso", &g_amec_sys.wof.all_caches_on_iso), diff --git a/src/occ_405/main.c b/src/occ_405/main.c index 0779319..eca4705 100755 --- a/src/occ_405/main.c +++ b/src/occ_405/main.c @@ -702,12 +702,18 @@ void read_pgpe_header(void) g_amec->wof.vfrt_tbls_main_mem_addr = in32(PGPE_WOF_TBLS_ADDR_PTR); g_amec->wof.vfrt_tbls_len = in32(PGPE_WOF_TBLS_LEN_PTR); + MAIN_TRAC_IMP("Read WOF Tables Main Memory Address[0x%08x], Len[0x%08x]," " Active Quads Address[0x%08x]", g_amec->wof.vfrt_tbls_main_mem_addr, g_amec->wof.vfrt_tbls_len, g_amec->wof.active_quads_sram_addr ); + // TODO: RTC 169955 - Read Vratio, Fratio, Vclip, Fclip from shared SRAM + g_amec->wof.v_ratio = 0; + g_amec->wof.f_ratio = 0; + g_amec->wof.v_clip = 0; + g_amec->wof.f_clip = 0; // Extract important WOF data into global space read_wof_header(); diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h index beb46b5..5df9ecc 100644 --- a/src/occ_405/occ_service_codes.h +++ b/src/occ_405/occ_service_codes.h @@ -125,6 +125,9 @@ enum occReasonCode WOF_VFRT_REQ_FAILURE = 0xD8, INVALID_MAGIC_NUMBER = 0xDA, + DIVIDE_BY_ZERO_ERROR = 0xDB, + + /// Success! OCC_SUCCESS_REASON_CODE = 0xFF, }; diff --git a/src/occ_405/wof/wof.c b/src/occ_405/wof/wof.c index b5df7b2..b54b691 100644 --- a/src/occ_405/wof/wof.c +++ b/src/occ_405/wof/wof.c @@ -45,7 +45,7 @@ extern GpeRequest G_wof_vfrt_req; extern uint32_t G_pgpe_shared_sram_address; extern uint32_t G_pgpe_pstate_table_address; extern uint32_t G_pgpe_pstate_table_sz; - +extern uint32_t G_nest_frequency_mhz; //****************************************************************************** // Globals //****************************************************************************** @@ -933,6 +933,191 @@ void calculate_nest_leakage( void ) g_wof->idc_vdn = (G_oppb.iddq.ivdn*nest_mult) >> 10; } + +/** + * calculate_effective_capacitance + * + * Description: Generic function to perform the effective capacitance + * calculations. + * C_eff = I / (V^1.3 * F) + * + * I is the AC component of Idd in 0.01 Amps (or10 mA) + * V is the silicon voltage in 100 uV + * F is the frequency in MHz + * + * Note: Caller must ensure they check for a 0 return value + * and disable wof if that is the case + * + * Param[in]: i_iAC - the AC component + * Param[in]: i_voltage - the voltage component in 100uV + * Param[in]: i_frequency - the frequency component + * + * Return: The calculated effective capacitance + */ +uint32_t calculate_effective_capacitance( uint32_t i_iAC, + uint32_t i_voltage, + uint32_t i_frequency ) +{ + + // Prevent divide by zero + if( i_frequency == 0 ) + { + // Return 0 causing caller to disable wof. + return 0; + } + + // Compute V^1.3 using a best-fit equation + // (V^1.3) = (21374 * (voltage in 100uV) - 50615296)>>10 + uint32_t v_exp_1_dot_3 = (21374 * i_voltage - 50615296)>>10; + + // Compute I / (V^1.3) + uint32_t I = i_iAC << 14; // * 16384 + + // Prevent divide by zero + if( v_exp_1_dot_3 == 0 ) + { + // Return 0 causing caller to disable wof. + return 0; + } + + uint32_t c_eff = (I / v_exp_1_dot_3); + c_eff = c_eff << 14; // * 16384 + + // Divide by frequency and return the final value. + // (I / (V^1.3 * F)) == I / V^1.3 /F + return c_eff / i_frequency; + +} + + + +/** + * calculate_ceff_ratio_vdn + * + * Description: Function to calculate the effective capacitance ratio + * for the nest + */ +void calculate_ceff_ratio_vdn( void ) +{ + //TODO Read iac_tdp_vdn(@turbo) from OCCPstateParmBlock struct + g_wof->iac_tdp_vdn = 0; + + // Calculate Ceff_tdp_vdn + // iac_tdp_vdn / (VOLTVDN^1.3 * Fnest) + g_wof->ceff_tdp_vdn = + calculate_effective_capacitance( g_wof->iac_tdp_vdn, + g_wof->voltvdn_sensor, + G_nest_frequency_mhz ); + + // Calculate ceff_vdn + // iac_vdn/ (VOLTVDN^1.3 * Fnest) + g_wof->ceff_vdn = + calculate_effective_capacitance( g_wof->iac_vdn, + g_wof->voltvdn_sensor, + G_nest_frequency_mhz ); + + // Prevent divide by zero + if( g_wof->ceff_tdp_vdn == 0 ) + { + /* + * @errortype + * @moduleid CALC_CEFF_RATIO_VDN + * @reasoncode DIVIDE_BY_ZERO_ERROR + * @userdata1 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Divide by zero error on ceff_vdn / ceff_tdp_vdn + */ + errlHndl_t l_errl = createErrl( + CALC_CEFF_RATIO_VDN, + DIVIDE_BY_ZERO_ERROR, + OCC_NO_EXTENDED_RC, + ERRL_SEV_PREDICTIVE, + NULL, + DEFAULT_TRACE_SIZE, + 0, + 0 ); + + commitErrl( &l_errl ); + + // Return 0 + g_wof->ceff_ratio_vdn = 0; + + //TODO: RTC 166301 - call new disable_wof function + } + else + { + g_wof->ceff_ratio_vdn = g_wof->ceff_vdn / g_wof->ceff_tdp_vdn; + } +} + +/** + * calculate_ceff_ratio_vdd + * + * Description: Function to calculate the effective capacitance ratio + * for the core + */ +void calculate_ceff_ratio_vdd( void ) +{ + //TODO read iac_tdp_vdd from OCCPstateParmBlock struct + g_wof->iac_tdp_vdd = 0; + + // Get Vturbo and convert to 100uV (mV -> 100uV) = mV*10 + // Multiply by Vratio + uint32_t V = (G_oppb.operating_points[TURBO].vdd_mv*10) * g_wof->v_ratio; + + // Get Fturbo and multiply by Fratio + uint32_t F = G_oppb.operating_points[TURBO].frequency_mhz * g_wof->f_ratio; + + // Calculate ceff_tdp_vdd + // iac_tdp_vdd / ((Vturbo*Vratio)^1.3 * (Fturbo*Fratio)) + g_wof->ceff_tdp_vdd = + calculate_effective_capacitance( g_wof->iac_tdp_vdd, + V, + F ); + + // Calculate ceff_vdd + // iac_vdd / (Vclip^1.3 * Fclip) + g_wof->ceff_vdd = + calculate_effective_capacitance( g_wof->iac_vdd, + g_wof->v_clip, + g_wof->f_clip ); + + // Prevent divide by zero + if( g_wof->ceff_tdp_vdd == 0 ) + { + /* + * @errortype + * @moduleid CALC_CEFF_RATIO_VDD + * @reasoncode DIVIDE_BY_ZERO_ERROR + * @userdata1 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Divide by zero error on ceff_vdd / ceff_tdp_vdd + */ + errlHndl_t l_errl = createErrl( + CALC_CEFF_RATIO_VDD, + DIVIDE_BY_ZERO_ERROR, + OCC_NO_EXTENDED_RC, + ERRL_SEV_PREDICTIVE, + NULL, + DEFAULT_TRACE_SIZE, + 0, + 0 ); + + commitErrl( &l_errl ); + + // Return 0 + g_wof->ceff_ratio_vdd = 0; + + //TODO: RTC 166301 - call new disable_wof function + } + else + { + g_wof->ceff_ratio_vdd = g_wof->ceff_vdd / g_wof->ceff_tdp_vdd; + } +} + + + /** * calculate_AC_currents * @@ -1054,11 +1239,18 @@ int32_t calculate_multiplier( int32_t i_temp ) (int32_t)G_wof_iddq_mult_table[mult_idx+1][1]); } +/** + * read_sensor_data + * + * Description: One time place to read out all the sensors needed + * for wof calculations. First thing wof_main does. + */ void read_sensor_data( void ) { // Read out necessary Sensor data for WOF calculation - g_wof->curvdd_sensor = getSensorByGsid(CURVDD)->sample; - g_wof->curvdn_sensor = getSensorByGsid(CURVDN)->sample; - g_wof->voltvddsense_sensor = getSensorByGsid(VOLTVDDSENSE)->sample; - g_wof->tempnest_sensor = getSensorByGsid(TEMPNEST)->sample; + g_wof->curvdd_sensor = getSensorByGsid(CURVDD)->sample; + g_wof->curvdn_sensor = getSensorByGsid(CURVDN)->sample; + g_wof->voltvddsense_sensor = getSensorByGsid(VOLTVDDSENSE)->sample; + g_wof->tempnest_sensor = getSensorByGsid(TEMPNEST)->sample; + g_wof->voltvdn_sensor = getSensorByGsid(VOLTVDN)->sample; } diff --git a/src/occ_405/wof/wof.h b/src/occ_405/wof/wof.h index 6d231a0..740a5f4 100644 --- a/src/occ_405/wof/wof.h +++ b/src/occ_405/wof/wof.h @@ -92,6 +92,8 @@ typedef struct uint16_t curvdd_sensor; // The most recently read value in the sensor CURVDN uint16_t curvdn_sensor; + // The most recently read value in the sensor VOLTVDN + uint16_t voltvdn_sensor; // Array to hold the current 1-byte pstate values read from SRAM. 0xFF=off uint8_t quad_x_pstates[MAX_NUM_QUADS]; // Bit vector to hold the ivrm states of the quads. 0=BYPASS, 1=REGULATION @@ -106,6 +108,30 @@ typedef struct uint32_t iac_vdd; // Contains the AC component of the workload for the nest uint32_t iac_vdn; + // Contains iac_tdp_vdd(@turbo) read from the pstate parameter block + uint32_t iac_tdp_vdd; + // Contains iac_tdp_vdn read from the pstate parameter block + uint32_t iac_tdp_vdn; + // Contains Vratio, read from OCC-PGPE shared SRAM + uint32_t v_ratio; + // Contains Fratio, read from OCC-PGPE shared SRAM + uint32_t f_ratio; + // Contains Vclip, read from OCC-PGPE shared SRAM + uint32_t v_clip; + // Contains Fclip, read from OCC-PGPE shared SRAM + uint32_t f_clip; + // Contains the calculated effective capacitance for tdp_vdd + uint32_t ceff_tdp_vdd; + // Contains the calculated effective capacitance for vdd + uint32_t ceff_vdd; + // Contains the calculated effective capacitance ratio for vdd + uint32_t ceff_ratio_vdd; + // Contains the calculated effective capacitance for tdp_vdn + uint32_t ceff_tdp_vdn; + // Contains the calculated effective capacitance for vdn + uint32_t ceff_vdn; + // Contains the calculated effective capacitance ratio for vdn + uint32_t ceff_ratio_vdn; // Contains the index used for interpolation in the ALL_CORES_OFF_ISO calc uint8_t voltage_idx; // Contains the final calculated value of ALL_CORES_OFF_ISO @@ -210,6 +236,10 @@ void calculate_core_leakage( void ); void calculate_nest_leakage( void ); +void calculate_ceff_ratio_vdn( void ); + +void calculate_ceff_ratio_vdd( void ); + inline void calculate_AC_currents( void ); inline bool core_powered_on( uint8_t i_core_num ); @@ -224,6 +254,11 @@ inline int32_t interpolate_linear( int32_t i_X, int32_t calculate_multiplier( int32_t i_temp ); +uint32_t calculate_effective_capacitance( uint32_t i_iAC, + uint32_t i_voltage, + uint32_t i_frequency ); + + void read_sensor_data( void ); #endif diff --git a/src/occ_405/wof/wof_service_codes.h b/src/occ_405/wof/wof_service_codes.h index 89afb3f..666ffa2 100644 --- a/src/occ_405/wof/wof_service_codes.h +++ b/src/occ_405/wof/wof_service_codes.h @@ -33,6 +33,10 @@ enum wofModuleId SEND_VFRT_TO_PGPE = WOF_COMP_ID | 0x02, COPY_VFRT_TO_SRAM = WOF_COMP_ID | 0x03, WOF_VFRT_CALLBACK = WOF_COMP_ID | 0x04, + CALC_EFF_CAP_VOLT = WOF_COMP_ID | 0x05, + CALC_EFF_CAP_FREQ = WOF_COMP_ID | 0x06, + CALC_CEFF_RATIO_VDD = WOF_COMP_ID | 0x07, + CALC_CEFF_RATIO_VDN = WOF_COMP_ID | 0x08, }; |