diff options
-rw-r--r-- | src/include/p9_pstates_common.h | 203 | ||||
-rw-r--r-- | src/include/p9_pstates_occ.h | 33 | ||||
-rw-r--r-- | src/include/pstate_pgpe_occ_api.h | 4 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_parm.h | 15 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_parm_table.c | 19 | ||||
-rw-r--r-- | src/occ_405/wof/wof.c | 448 | ||||
-rw-r--r-- | src/occ_405/wof/wof.h | 54 |
7 files changed, 422 insertions, 354 deletions
diff --git a/src/include/p9_pstates_common.h b/src/include/p9_pstates_common.h index 003021c..d776534 100644 --- a/src/include/p9_pstates_common.h +++ b/src/include/p9_pstates_common.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -267,140 +267,179 @@ typedef struct // // WOF Voltage, Frequency Ratio Tables // +//VFRT calculation part +#define SYSTEM_VERSION_FRQUENCY(VFRT) (1000 + (16.67 * VFRT)) +#define SYSTEM_VFRT_VALUE(FREQ) ((FREQ - 1000)/16.67) -// VFRT Header -typedef struct -{ +#define HOMER_VFRT_VALUE(FREQ,BSF) ((BSF - FREQ)/16.67) +#define HOMER_VERSION_FREQUENCY(VFRT,BSF) (BSF - (16.67 * VFRT)) - /// Magic Number - /// Set to ASCII "VT" - uint16_t magic_number; - /// Indicator - /// Space for generation tools to be anything unique necessary to ID this - /// VFRT - uint16_t indicator; - - union - { - uint8_t value; - struct - { - uint8_t type : 4; - uint8_t version : 4; - } fields; - } typever; - - uint8_t reserved; - - union - { - uint16_t value; - struct - { -#ifdef _BIG_ENDIAN - uint16_t reserved: 4; - uint16_t vdn_id : 4; - uint16_t vdd_id : 4; - uint16_t qa_id : 4; -#else - uint16_t qa_id : 4; - uint16_t vdd_id : 4; - uint16_t vdn_id : 4; - uint16_t reserved: 4; -#endif // _BIG_ENDIAN - - } fields; - } ids; - -} VFRTHeader_t; - -// WOF Tables Header +//VFRT Header fields +typedef struct __attribute__((__packed__)) VFRTHeaderLayout +{ + // VFRT Magic code "VT" + uint16_t magic_number; -typedef struct + uint16_t reserved_1; + // 0:System type, 1:Homer type (0:3) + // if version 1: VFRT size is 12 row(voltage) X 11 column(freq) of size uint8_t + // (4:7) + // if version 2: VFRT size is 24 row(Voltage) X 5 column (Freq) of size uint8_t + uint8_t type_version; + //Reserved + uint8_t reserved_2; + //Identifies the Vdn assumptions tht went in this VFRT (4:7) + uint8_t res_vdnId; + //Identifies the Vdd assumptions tht went in this VFRT (0:4) + //Identifies the Quad Active assumptions tht went in this VFRT (5:7) + uint8_t VddId_QAId; +} VFRTHeaderLayout_t;// WOF Tables Header + +typedef struct __attribute__((__packed__)) WofTablesHeader { /// Magic Number - /// Set to ASCII "VFRT___x" where x is the version of the VFRT structure - uint64_t magic_number; + /// Set to ASCII "WFTH___x" where x is the version of the VFRT structure + uint32_t magic_number; - /// VFRT Size + uint32_t reserved_version; // reserved:24b, version:8b + + /// VFRT Block Size /// Length, in bytes, of a VFRT - uint8_t vfrt_size; + uint16_t vfrt_block_size; + + /// VFRT block header size + uint16_t vfrt_block_header_size; /// VFRT Data Size /// Length, in bytes, of the data field. - uint8_t vfrt_data_size; - - uint8_t reserved; + uint16_t vfrt_data_size; /// Quad Active Size /// Total number of Active Quads uint8_t quads_active_size; + /// Core count + uint8_t core_count; + /// Ceff Vdn Start - /// CeffVdn value represented by index 0 (in percent) - uint8_t vdn_start; + /// CeffVdn value represented by index 0 (in 0.01%) + uint16_t vdn_start; /// Ceff Vdn Step - /// CeffVdn step value for each CeffVdn index (in percent) - uint8_t vdn_step; + /// CeffVdn step value for each CeffVdn index (in 0.01%) + uint16_t vdn_step; /// Ceff Vdn Size /// Number of CeffVdn indexes - uint8_t vdn_size; + uint16_t vdn_size; /// Ceff Vdd Start - /// CeffVdd value represented by index 0 (in percent) - uint8_t vdd_start; + /// CeffVdd value represented by index 0 (in 0.01%) + uint16_t vdd_start; /// Ceff Vdd Step - /// CeffVdd step value for each CeffVdd index (in percent) - uint8_t vdd_step; + /// CeffVdd step value for each CeffVdd index (in 0.01%) + uint16_t vdd_step; /// Ceff Vdd Size /// Number of CeffVdd indexes - uint8_t vdd_size; + uint16_t vdd_size; /// Vratio Start - /// Vratio value represented by index 0 (in percent) - uint8_t vratio_start; + /// Vratio value represented by index 0 (in 0.01%) + uint16_t vratio_start; /// Vratio Step - /// Vratio step value for each CeffVdd index (in percent) - uint8_t vratio_step; + /// Vratio step value for each CeffVdd index (in 0.01%) + uint16_t vratio_step; /// Vratio Size /// Number of Vratio indexes - uint8_t vratio_size; + uint16_t vratio_size; /// Fratio Start - /// Fratio value represented by index 0 (in percent) - uint8_t fratio_start; + /// Fratio value represented by index 0 (in 0.01%) + uint16_t fratio_start; /// Fratio Step - /// Fratio step value for each CeffVdd index (in percent) - uint8_t fratio_step; + /// Fratio step value for each CeffVdd index (in 0.01%) + uint16_t fratio_step; /// Fratio Size /// Number of Fratio indexes - uint8_t fratio_size; + uint16_t fratio_size; + + /// Future usage + uint16_t Vdn_percent[8]; + + ///Socket Power (in Watts) for the WOF Tables + uint16_t socket_power_w; + + ///Nest Frequency (in MHz) used in building the WOF Tables + uint16_t nest_frequency_mhz; + + //Core Sort Power Target Frequency (in MHz) – The #V frequency associated + //with the sort power target for this table set. This will be either the + //Nominal or + //Turbo #V frequency + uint16_t sort_power_freq_mhz; + + ///Regulator Design Point Capacity (in Amps) + uint16_t rdp_capacity; + + ///Up to 8 ASCII characters to be defined by the Table generation team to + //back reference table sources + uint64_t wof_table_source_tag; + + ///Up to 16 ASCII characters as a Package designator + uint64_t package_name; + + uint8_t reserved[6]; } WofTablesHeader_t; -// VDN -// Data is provided in 12ths (eg 12 core pairs on a 24 core chip) -#define VFRT_VRATIO_SIZE 12 +#define CEF_VDN_INDEX 8 +#define CEF_VDD_INDEX 21 +#define ACTIVE_QUADS 6 + +// Data is provided in 1/24ths granularity with adjustments for integer +// representation +#define VFRT_VRATIO_SIZE 24 + +// 5 steps down from 100% is Fratio_step sizes +#define VFRT_FRATIO_SIZE 5 -// 100%/10% steps -#define VFRT_FRATIO_SIZE 10 +//System VFRT layout +typedef struct __attribute__((__packed__)) HomerSysVFRTLayout +{ + VFRTHeaderLayout_t vfrtHeader; + uint8_t vfrt_data[VFRT_VRATIO_SIZE][VFRT_FRATIO_SIZE]; +} HomerSysVFRTLayout_t; + + + +//HOMER VFRT Layout +typedef struct __attribute__((__packed__)) HomerVFRTLayout +{ + VFRTHeaderLayout_t vfrtHeader; + uint8_t vfrt_data[VFRT_VRATIO_SIZE][VFRT_FRATIO_SIZE]; + uint8_t padding[128]; +} HomerVFRTLayout_t; + +//HOMER WOF layout +typedef struct __attribute__((__packed__)) HomerWOFLayout +{ + WofTablesHeader_t wof_header_data; + HomerVFRTLayout_t homer_vfrt_data[CEF_VDN_INDEX][CEF_VDD_INDEX][ACTIVE_QUADS]; +} HomerWOFLayout_t; -// Holds a frequency that is 1000MHz + 16.667*VFRT_Circuit_t typedef uint8_t VFRT_Circuit_t; -typedef Pstate VFRT_Hcode_t; +typedef Pstate VFRT_Hcode_t; diff --git a/src/include/p9_pstates_occ.h b/src/include/p9_pstates_occ.h index 26b97eb..fb295e7 100644 --- a/src/include/p9_pstates_occ.h +++ b/src/include/p9_pstates_occ.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -98,11 +98,14 @@ typedef struct /// WOF Iddq Margin (aging factor) in 0.01% units uint16_t wof_iddq_margin_factor; - /// Temperature Scale Factor per 10C in 0.01% units - uint16_t temperature_scale_factor; + /// VDD Temperature Scale Factor per 10C in 0.01% units + uint16_t vdd_temperature_scale_factor; + + /// VDN Temperature Scale Factor per 10C in 0.01% units + uint16_t vdn_temperature_scale_factor; /// Spare - uint8_t spare[10]; + uint8_t spare[8]; /// IVDD ALL Good Cores ON; 6.25mA units iddq_entry_t ivdd_all_good_cores_on_caches_on[IDDQ_MEASUREMENTS]; @@ -133,11 +136,15 @@ typedef struct avgtemp_entry_t avgtemp_quad_good_cores_on[MAXIMUM_QUADS][IDDQ_MEASUREMENTS]; /// avgtempN ; 6.25mA units - avgtemp_entry_t avgtemp_vdn; + avgtemp_entry_t avgtemp_vdn[IDDQ_MEASUREMENTS]; /// spare (per MVPD documentation - uint8_t spare_1[43]; - + /// + /// NOTE: The MVPD documentation defines 43 spare bytes to lead to a 255B structure. However, + /// some consuming code already assumed a 250B structure and the correction of this size was disruptive. + /// This is not a problem until the IQ keyword actually defines these bytes at which time a keyword + /// version update will be need. Thus, this structure will remain at 250B. + uint8_t spare_1[38]; } IddqTable; @@ -187,6 +194,18 @@ typedef struct /// Nest frequency in Mhz. This is used by FIT interrupt uint32_t nest_frequency_mhz; + + //Nest leakage percentage used to calculate the Core leakage + uint16_t nest_leakage_percent; + + uint16_t ceff_tdp_vdn; + + // AC tdp vdd turbo + uint16_t lac_tdp_vdd_turbo_10ma; + + // AC tdp vdd nominal + uint16_t lac_tdp_vdd_nominal_10ma; + } __attribute__((aligned(128))) OCCPstateParmBlock; #ifdef __cplusplus diff --git a/src/include/pstate_pgpe_occ_api.h b/src/include/pstate_pgpe_occ_api.h index 6768617..bd70283 100644 --- a/src/include/pstate_pgpe_occ_api.h +++ b/src/include/pstate_pgpe_occ_api.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -138,7 +138,7 @@ typedef struct ipcmsg_wof_vfrt uint8_t active_quads; // OCC updated with the Active Quads that it // is using for its Ceff calculations uint8_t pad; - VFRT_Hcode_t* vfrt_ptr; // Voltage Frequency Ratio Table + HomerVFRTLayout_t* homer_vfrt_ptr; // Voltage Frequency Ratio Table } ipcmsg_wof_vfrt_t; diff --git a/src/occ_405/amec/amec_parm.h b/src/occ_405/amec/amec_parm.h index 3b3a4ba..b2dc580 100755 --- a/src/occ_405/amec/amec_parm.h +++ b/src/occ_405/amec/amec_parm.h @@ -107,8 +107,11 @@ typedef enum PARM_TEMPPROCTHERMC, PARM_TEMPNEST, PARM_TEMPQ, + PARM_CURVDD_SENSE, + PARM_CURVDN_SENSE, PARM_VOLTVDN, PARM_QUAD_X_PSTATES, + PARM_QUAD_V_IDX, PARM_IVRM_STATES, PARM_IDC_VDD, PARM_IDC_VDN, @@ -116,7 +119,6 @@ typedef enum PARM_IAC_VDD, PARM_IAC_VDN, PARM_IAC_TDP_VDD, - PARM_IAC_TDP_VDN, PARM_VOLTAGE_IDX, PARM_V_RATIO, PARM_F_RATIO, @@ -133,16 +135,6 @@ typedef enum PARM_QUAD_GOOD_CORES_ONLY, PARM_QUAD_ON_CORES, PARM_QUAD_BAD_OFF_CORES, - PARM_NEST_MULT, - PARM_CORE_MULT, - PARM_QUAD_MULT, - PARM_NEST_DELTA_TEMP, - PARM_CORE_DELTA_TEMP, - PARM_QUAD_DELTA_TEMP, - PARM_TVPD_LEAK_OFF, - PARM_TVPD_LEAK_ON, - PARM_TVPD_LEAK_CACHE, - PARM_TVPD_LEAK_NEST, PARM_REQ_ACTIVE_QUAD_UPDATE, PARM_PREV_REQ_ACTIVE_QUADS, PARM_NUM_ACTIVE_QUADS, @@ -157,6 +149,7 @@ typedef enum PARM_QUAD_STATE_1_ADDR, PARM_PGPE_WOF_STATE_ADDR, PARM_REQ_ACTIVE_QUADS_ADDR, + PARM_CORE_LEAKAGE_PERCENT, // End WOF Parameters AMEC_PARM_NUMBER_OF_PARAMETERS } AMEC_PARM_ENUM; diff --git a/src/occ_405/amec/amec_parm_table.c b/src/occ_405/amec/amec_parm_table.c index b48cef1..5aca19d 100755 --- a/src/occ_405/amec/amec_parm_table.c +++ b/src/occ_405/amec/amec_parm_table.c @@ -180,8 +180,11 @@ 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, MAXIMUM_QUADS), + AMEC_PARM_UINT16(PARM_CURVDD_SENSE, "curvdd", &g_amec_sys.wof.curvdd_sensor), + AMEC_PARM_UINT16(PARM_CURVDN_SENSE, "curvdn", &g_amec_sys.wof.curvdn_sensor), 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, MAXIMUM_QUADS), + AMEC_PARM_UINT8_ARRAY(PARM_QUAD_V_IDX, "quad_v_idx", &g_amec_sys.wof.quad_v_idx, MAXIMUM_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), AMEC_PARM_UINT32(PARM_IDC_VDN, "idc_vdn", &g_amec_sys.wof.idc_vdn), @@ -189,7 +192,6 @@ amec_parm_t g_amec_parm_list[] = { 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), @@ -201,22 +203,12 @@ amec_parm_t g_amec_parm_list[] = { 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_UINT8(PARM_VOLTAGE_IDX, "voltage_idx", &g_amec_sys.wof.chip_volt_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), + AMEC_PARM_UINT32(PARM_ALL_CACHES_ON_ISO, "allcaches_on_iso", &g_amec_sys.wof.all_good_caches_on_iso), AMEC_PARM_UINT16_ARRAY(PARM_QUAD_GOOD_CORES_ONLY, "quad_good_cores", &g_amec_sys.wof.quad_good_cores_only, MAXIMUM_QUADS), AMEC_PARM_UINT16_ARRAY(PARM_QUAD_ON_CORES, "quad_on_cores", &g_amec_sys.wof.quad_on_cores, MAXIMUM_QUADS), AMEC_PARM_UINT16_ARRAY(PARM_QUAD_BAD_OFF_CORES,"quadBadOffCores", &g_amec_sys.wof.quad_on_cores, MAXIMUM_QUADS), - AMEC_PARM_UINT32(PARM_NEST_MULT, "nest_mult", &g_amec_sys.wof.nest_mult), - AMEC_PARM_UINT32_ARRAY(PARM_CORE_MULT, "core_mult", &g_amec_sys.wof.core_mult, MAX_NUM_CORES), - AMEC_PARM_UINT32_ARRAY(PARM_QUAD_MULT, "quad_mult", &g_amec_sys.wof.quad_mult, MAXIMUM_QUADS), - AMEC_PARM_INT16(PARM_NEST_DELTA_TEMP, "nest_delta_temp", &g_amec_sys.wof.nest_delta_temp), - AMEC_PARM_INT16_ARRAY(PARM_CORE_DELTA_TEMP, "core_delta_temp", &g_amec_sys.wof.core_delta_temp, MAX_NUM_CORES), - AMEC_PARM_INT16_ARRAY(PARM_QUAD_DELTA_TEMP, "quad_delta_temp", &g_amec_sys.wof.quad_delta_temp, MAX_NUM_CORES), - AMEC_PARM_UINT16(PARM_TVPD_LEAK_OFF, "tvpd_leak_off", &g_amec_sys.wof.tvpd_leak_off), - AMEC_PARM_UINT16(PARM_TVPD_LEAK_ON, "tvpd_leak_on", &g_amec_sys.wof.tvpd_leak_on), - AMEC_PARM_UINT16(PARM_TVPD_LEAK_CACHE, "tvpd_leak_cache", &g_amec_sys.wof.tvpd_leak_cache), - AMEC_PARM_UINT16(PARM_TVPD_LEAK_NEST, "tvpd_leak_nest", &g_amec_sys.wof.tvpd_leak_nest), AMEC_PARM_UINT8(PARM_REQ_ACTIVE_QUAD_UPDATE, "req_active_quad", &g_amec_sys.wof.req_active_quad_update), AMEC_PARM_UINT8(PARM_PREV_REQ_ACTIVE_QUADS, "prevActiveQuads", &g_amec_sys.wof.prev_req_active_quads), AMEC_PARM_UINT8(PARM_NUM_ACTIVE_QUADS, "num_active_quads", &g_amec_sys.wof.num_active_quads), @@ -231,6 +223,7 @@ amec_parm_t g_amec_parm_list[] = { AMEC_PARM_UINT32(PARM_QUAD_STATE_1_ADDR, "quadSt1Addr", &g_amec_sys.wof.quad_state_1_addr), AMEC_PARM_UINT32(PARM_PGPE_WOF_STATE_ADDR, "pgpeWofStAddr", &g_amec_sys.wof.pgpe_wof_state_addr), AMEC_PARM_UINT32(PARM_REQ_ACTIVE_QUADS_ADDR, "reqActQuadAddr", &g_amec_sys.wof.req_active_quads_addr), + AMEC_PARM_UINT16(PARM_CORE_LEAKAGE_PERCENT, "coreLeakPercent", &g_amec_sys.wof.core_leakage_percent), // End WOF parameters }; diff --git a/src/occ_405/wof/wof.c b/src/occ_405/wof/wof.c index 3050c52..27a7dd1 100644 --- a/src/occ_405/wof/wof.c +++ b/src/occ_405/wof/wof.c @@ -497,7 +497,7 @@ void copy_vfrt_to_sram( copy_vfrt_to_sram_parms_t * i_parms) G_wof_header.vfrt_block_size ); // Set the parameters for the GpeRequest - G_wof_vfrt_parms.vfrt_ptr = l_buffer_address; + G_wof_vfrt_parms.homer_vfrt_ptr = (HomerVFRTLayout_t*)l_buffer_address; G_wof_vfrt_parms.active_quads = g_wof->req_active_quad_update; // Send IPC command to PGPE with new vfrt address and active quads @@ -757,8 +757,8 @@ void calculate_core_voltage( void ) { uint32_t l_voltage; uint8_t l_quad_mask; - int l_quad_idx = 0; - for(; l_quad_idx < MAXIMUM_QUADS; l_quad_idx++) + int l_quad_idx; + for(l_quad_idx = 0; l_quad_idx < MAXIMUM_QUADS; l_quad_idx++) { // Adjust current mask. (IVRM_STATE_QUAD_MASK = 0x80) l_quad_mask = IVRM_STATE_QUAD_MASK >> l_quad_idx; @@ -790,6 +790,9 @@ void calculate_core_voltage( void ) } // Save the voltage to amec_wof_t global struct g_wof->v_core_100uV[l_quad_idx] = l_voltage; + + // Save off the voltage index for later use + g_wof->quad_v_idx[l_quad_idx] = get_voltage_index(l_voltage); } } @@ -802,8 +805,8 @@ void calculate_core_voltage( void ) */ void calculate_core_leakage( void ) { - int l_chip_v_idx = 0; - uint16_t l_quad_x_cache; + int l_chip_v_idx; + uint16_t l_quad_cache; uint16_t idc_vdd = 0; uint8_t num_quads_off = 0; uint16_t temperature = 0; @@ -812,80 +815,56 @@ void calculate_core_leakage( void ) // chip voltage index uint32_t l_v_chip = g_wof->voltvddsense_sensor; - if( l_v_chip <= G_iddq_voltages[0] ) - { - // Voltage is <= to first entry. Use first two entries. - l_chip_v_idx = 0; - } - else if( l_v_chip >= G_iddq_voltages[CORE_IDDQ_MEASUREMENTS-1] ) - { - // Voltage is >= to last entry. Use last two entries. - l_chip_v_idx = CORE_IDDQ_MEASUREMENTS - 2; - } - else - { - // Search for entries on either side of our voltage - for(;l_chip_v_idx < CORE_IDDQ_MEASUREMENTS - 1; l_chip_v_idx++) - { - if( (l_v_chip >= G_iddq_voltages[l_chip_v_idx]) && - (l_v_chip <= G_iddq_voltages[l_chip_v_idx+1]) ) - { - break; - } - } + // Choose the lower bound index of G_iddq_voltages + l_chip_v_idx = get_voltage_index( l_v_chip ); - } // Save index used for interpolating voltages to amec - g_wof->voltage_idx = l_chip_v_idx; + g_wof->chip_volt_idx = l_chip_v_idx; // Calculate all variables that will be used in the core // loop that only need to be calculated once. - // Look up Tvpd_leak for calculations when either the core or quad is off - // avttemp values in 0.5C. Divide by 2 to convert to 1C - g_wof->tvpd_leak_off = - G_oppb.iddq.avgtemp_all_cores_off_caches_off[l_chip_v_idx] >> 1; - - // Look up Tvpd_leak for calculations involving the cache. - g_wof->tvpd_leak_cache = - G_oppb.iddq.avgtemp_all_good_cores_off[l_chip_v_idx] >> 1; - - // Take the difference between the temperature and tvpd_leak_off - // used for multiplier calculation - g_wof->nest_delta_temp = g_wof->tempnest_sensor - - g_wof->tvpd_leak_off; - - // Calculate IDDQ_TEMP_FACTOR^((TEMPNEST - tvpd_leak)/10) - g_wof->nest_mult = calculate_multiplier(g_wof->nest_delta_temp); - - // Look up leakage current. - // Divide by 6 to get just one quad - g_wof->idc_quad = - G_oppb.iddq.ivdd_all_cores_off_caches_off[l_chip_v_idx] / - MAXIMUM_QUADS; - - // Calculate ALL_CORES_OFF_ISO - // Perform linear interpolation using the neighboring entries: - // Y = m*(X-x1) + y1, where m = (y2-y1) / (x2-x1) + // ALL_CORES_OFF_ISO g_wof->all_cores_off_iso = - interpolate_linear((int32_t)l_v_chip, - (int32_t)G_iddq_voltages[l_chip_v_idx], - (int32_t)G_iddq_voltages[l_chip_v_idx+1], - (int32_t)G_oppb.iddq.ivdd_all_cores_off_caches_off[l_chip_v_idx], - (int32_t)G_oppb.iddq.ivdd_all_cores_off_caches_off[l_chip_v_idx+1]); - - // Multiply by nest leakage percentage - // TODO: This percentage(60%) will eventually be added to the OCC Pstate Parameter - // block once it is added as a system attribute to the MRW. - // G_oppb.iddq.nestLeakagePercentage - g_wof->all_cores_off_iso = g_wof->all_cores_off_iso * 60 / 100; - - // Calculate ALL_CACHES_ON_ISO - g_wof->all_caches_on_iso = - G_oppb.iddq.ivdd_all_good_cores_off_good_caches_on[l_chip_v_idx] - - g_wof->all_cores_off_iso; - - l_quad_x_cache = g_wof->all_caches_on_iso / MAXIMUM_QUADS; + scale_and_interpolate( G_oppb.iddq.ivdd_all_cores_off_caches_off, + G_oppb.iddq.avgtemp_all_cores_off_caches_off, + l_chip_v_idx, + g_wof->tempnest_sensor, + l_v_chip ); + + // Get the core leakage percent from the OPPB + // Note: This value is named inaccurately in the OPPB so we are reassigning + // it's value here. We are also making the value visible to amester here. + g_wof->core_leakage_percent = G_oppb.nest_leakage_percent; + + // Multiply by core leakage percentage + g_wof->all_cores_off_iso = g_wof->all_cores_off_iso * + g_wof->core_leakage_percent / 100; + + // Calculate ALL_GOOD_CACHES_ON_ISO + g_wof->all_good_caches_on_iso = + scale_and_interpolate( G_oppb.iddq.ivdd_all_good_cores_off_good_caches_on, + G_oppb.iddq.avgtemp_all_good_cores_off, + l_chip_v_idx, + g_wof->tempnest_sensor, + l_v_chip ) - g_wof->all_cores_off_iso; + + // Calculate ALL_CACHES_OFF_ISO + g_wof->all_caches_off_iso = + scale_and_interpolate( G_oppb.iddq.ivdd_all_cores_off_caches_off, + G_oppb.iddq.avgtemp_all_cores_off_caches_off, + l_chip_v_idx, + g_wof->tempnest_sensor, + l_v_chip ) - g_wof->all_cores_off_iso; + + // idc Quad uses same variables as all_cores_off_iso so just use that and + // divide by 6 to get just one quad + g_wof->idc_quad = g_wof->all_cores_off_iso / MAXIMUM_QUADS; + + // Calculate quad_cache for all quads + l_quad_cache = ( g_wof->all_good_caches_on_iso - g_wof->all_caches_off_iso * + ( MAXIMUM_QUADS - G_oppb.iddq.good_quads_per_sort) / + MAXIMUM_QUADS ) / G_oppb.iddq.good_quads_per_sort; // Loop through all Quads and their respective Cores to calculate // leakage. @@ -904,39 +883,28 @@ void calculate_core_leakage( void ) else // Quad i is on { // Calculate the index of the first core in the quad. + // so we reference the correct one in the inner core loop core_idx = quad_idx * NUM_CORES_PER_QUAD; // Get the voltage for the current core. // (Same for all cores within a single quad) - uint16_t cur_core_voltage = g_wof->v_core_100uV[quad_idx]; + uint8_t quad_v_idx = g_wof->quad_v_idx[quad_idx]; // Calculate the number of cores on within the current quad. g_wof->cores_on_per_quad[quad_idx] = num_cores_on_in_quad(quad_idx); - // Look up tvpd_leak_on for calculations when the core/quad is on - // avttemp in IDDQ table is in 0.5C. Divide by 2 to convert to 1C. - g_wof->tvpd_leak_on = G_oppb.iddq.avgtemp_quad_good_cores_on - [quad_idx][cur_core_voltage] >> 1; - - // Calculate Quadx_good_cores_only - g_wof->quad_good_cores_only[quad_idx] = - G_oppb.iddq.ivdd_quad_good_cores_on_good_caches_on - [quad_idx][cur_core_voltage] - - G_oppb.iddq.ivdd_all_good_cores_off_good_caches_on - [l_chip_v_idx] + - g_wof->all_cores_off_iso* - G_oppb.iddq.good_normal_cores[quad_idx]/24; - - // Calculate quadx_ON_cores - g_wof->quad_on_cores[quad_idx] = - (g_wof->quad_good_cores_only[quad_idx]* - g_wof->cores_on_per_quad[quad_idx]) / - G_oppb.iddq.good_normal_cores[quad_idx]; - // Calculate quadx_BAD_OFF_cores - g_wof->quad_bad_off_cores[quad_idx] = - g_wof->all_cores_off_iso*G_oppb.iddq.good_normal_cores[quad_idx]/24; + // Take a snap shot of the quad temperature for later calculations + g_wof->tempq[quad_idx] = AMECSENSOR_ARRAY_PTR(TEMPQ0, + quad_idx)->sample; + // If 0, use nest temperature. + if( g_wof->tempq[quad_idx] == 0 ) + { + g_wof->tempq[quad_idx] = g_wof->tempnest_sensor; + } + + // Reset num_cores_off_in_quad before processing current quads cores uint8_t num_cores_off_in_quad = 0; @@ -945,39 +913,49 @@ void calculate_core_leakage( void ) { if(core_powered_on(core_idx)) { + // Get the core temperature from TEMPPROCTHRMC sensor temperature = AMECSENSOR_ARRAY_PTR(TEMPPROCTHRMC0, core_idx)->sample; - // If the TEMPPROCTHRMCy is 0, use TEMPQx + // If TEMPPROCTHRMCy is 0, use TEMPQx if(temperature == 0) { - temperature = AMECSENSOR_ARRAY_PTR(TEMPQ0, - quad_idx)->sample; - // If TEMPQx is also 0, use TEMPNEST - if(temperature == 0) - { - temperature = g_wof->tempnest_sensor; - } + // Quad temp guaranteed to be non-zero. Check was made + // when assigning to tempq array. + temperature = g_wof->tempq[quad_idx]; } - // Save the selected temperature + // Save selected temperature g_wof->tempprocthrmc[core_idx] = temperature; - // Get the difference between the temperature and tvpd_leak - g_wof->core_delta_temp[core_idx] = - g_wof->tempprocthrmc[core_idx] - - g_wof->tvpd_leak_on; - - // Calculate the multiplier for the core - g_wof->core_mult[core_idx] = - calculate_multiplier(g_wof->core_delta_temp[core_idx]); - - // For each core, incorporate core on calculation into - // leakage - idc_vdd += (g_wof->quad_on_cores[quad_idx]* - g_wof->core_mult[core_idx]) >> 10; - + g_wof->quad_good_cores_only[quad_idx] = + scale_and_interpolate + (G_oppb.iddq.ivdd_quad_good_cores_on_good_caches_on[quad_idx], + G_oppb.iddq.avgtemp_quad_good_cores_on[quad_idx], + quad_v_idx, + g_wof->tempprocthrmc[core_idx], + g_wof->v_core_100uV[quad_idx] ) + - + scale_and_interpolate + (G_oppb.iddq.ivdd_all_good_cores_off_good_caches_on, + G_oppb.iddq.avgtemp_all_good_cores_off, + quad_v_idx, + g_wof->tempprocthrmc[core_idx], + g_wof->v_core_100uV[quad_idx]) + + + g_wof->all_cores_off_iso * + G_oppb.iddq.good_normal_cores[quad_idx] / 24; + + + // Calculate quad_on_cores[quad] + g_wof->quad_on_cores[quad_idx] = + (g_wof->quad_good_cores_only[quad_idx]* + g_wof->cores_on_per_quad[quad_idx]) / + G_oppb.iddq.good_normal_cores[quad_idx]; + + // Add to overall leakage + idc_vdd += g_wof->quad_on_cores[quad_idx]; } else // Core is powered off { @@ -989,45 +967,35 @@ void calculate_core_leakage( void ) } // core loop // After all cores within the current quad have been processed, - // incorporate calculation for cores that were off into leakage - idc_vdd += - ((g_wof->quad_bad_off_cores[quad_idx]*g_wof->nest_mult) - >> 10)* num_cores_off_in_quad; - - temperature = AMECSENSOR_ARRAY_PTR(TEMPQ0, - quad_idx)->sample; - - // If TEMPQ0 is 0, use TEMPNEST - if( temperature == 0 ) - { - temperature = g_wof->tempnest_sensor; - } - - // Save selected temperature off to amec - g_wof->tempq[quad_idx] = temperature; - - - // Get the quad delta temperature for cache calc - g_wof->quad_delta_temp[quad_idx] = - g_wof->tempq[quad_idx] - - g_wof->tvpd_leak_cache; - - //Calculate the multiplier for the quad - g_wof->quad_mult[quad_idx] = - calculate_multiplier(g_wof->quad_delta_temp[quad_idx]); - - // Incorporate the cache into the leakage calculation - idc_vdd += (l_quad_x_cache*g_wof->quad_mult[quad_idx]) >> 10; + // incorporate calculations for cores that were off into leakage + // Calculate quadx_BAD_OFF_cores + g_wof->quad_bad_off_cores[quad_idx] = + g_wof->all_cores_off_iso * + G_oppb.iddq.good_normal_cores[quad_idx]/24; - } + // Scale to nest temp and add to overall leakage + idc_vdd += + (scale(g_wof->quad_bad_off_cores[quad_idx], + (g_wof->tempnest_sensor - + (G_oppb.iddq.avgtemp_all_cores_off_caches_off[quad_v_idx]>>1)))) + * num_cores_off_in_quad; + // After all cores have been processed in current quad, multiply + // the scaled value by the numer of cores that were off. + + // Incorporate the cache into leakage calculation. + // scale from nest to quad + idc_vdd += scale( l_quad_cache, + ( g_wof->tempq[quad_idx] - g_wof->tempnest_sensor) ); + + } // quad on/off conditional } // quad loop + // After all Quads have been processed, incorporate calculation for quads // that off into leakage - idc_vdd += ((g_wof->idc_quad*g_wof->nest_mult) >> 10)* num_quads_off; + idc_vdd += g_wof->idc_quad * num_quads_off; // Finally, save the calculated leakage to amec g_wof->idc_vdd = idc_vdd; - } /** @@ -1039,53 +1007,17 @@ void calculate_core_leakage( void ) void calculate_nest_leakage( void ) { - // Get the VOLTVDN sensor to choose the appropriate nest voltage // index - uint32_t l_v_nest = g_wof->voltvdn_sensor; - int l_nest_v_idx = 0; - - if( l_v_nest <= G_iddq_voltages[0] ) - { - // Voltage is <= first entry. Use first two entries. - l_nest_v_idx = 0; - } - else if( l_v_nest >= G_iddq_voltages[CORE_IDDQ_MEASUREMENTS-1] ) - { - // Voltage is >= to last entry. use last two entries. - l_nest_v_idx = CORE_IDDQ_MEASUREMENTS - 2; - } - else - { - // Search for entries on either side of our voltage - for(; l_nest_v_idx < CORE_IDDQ_MEASUREMENTS - 1; l_nest_v_idx++) - { - if( (l_v_nest >= G_iddq_voltages[l_nest_v_idx]) && - (l_v_nest <= G_iddq_voltages[l_nest_v_idx+1]) ) - { - break; - } - } - } - - uint32_t idc_nest = interpolate_linear((int32_t) l_v_nest, - (int32_t)G_iddq_voltages[l_nest_v_idx], - (int32_t)G_iddq_voltages[l_nest_v_idx+1], - (int32_t)G_oppb.iddq.ivdn[l_nest_v_idx], - (int32_t)G_oppb.iddq.ivdn[l_nest_v_idx+1]); - - // Get the desired tvpd leak for nest calculation - // avgtemp in IDDQ table is 0.5C units. Divide by 2 to get 1C - g_wof->tvpd_leak_nest = G_oppb.iddq.avgtemp_vdn >> 1; - - // Subtract tvpd_leak from TEMPNEST sensor - int16_t nest_delta_temp = g_wof->tempnest_sensor - g_wof->tvpd_leak_nest; - - // Calculate multiplier for final calculation; - uint32_t nest_mult = calculate_multiplier( nest_delta_temp ); - - // Save nest leakage to amec structure - g_wof->idc_vdn = (idc_nest*nest_mult) >> 10; + int l_nest_v_idx = get_voltage_index( g_wof->voltvdn_sensor ); + + // Assign to nest leakage. + g_wof->idc_vdn = + scale_and_interpolate(G_oppb.iddq.ivdn, + G_oppb.iddq.avgtemp_vdn, + l_nest_v_idx, + g_wof->tempnest_sensor, + g_wof->voltvdn_sensor ); } /** @@ -1150,15 +1082,8 @@ uint32_t calculate_effective_capacitance( uint32_t i_iAC, */ 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 ); + // Get ceff_tdp_vdn from OCCPPB + g_wof->ceff_tdp_vdn = G_oppb.ceff_tdp_vdn; // Calculate ceff_vdn // iac_vdn/ (VOLTVDN^1.3 * Fnest) @@ -1210,8 +1135,8 @@ void calculate_ceff_ratio_vdn( void ) */ void calculate_ceff_ratio_vdd( void ) { - //TODO read iac_tdp_vdd from OCCPstateParmBlock struct - g_wof->iac_tdp_vdd = 0; + // Read iac_tdp_vdd from OCCPstateParmBlock struct + g_wof->iac_tdp_vdd = G_oppb.lac_tdp_vdd_turbo_10ma; // Get Vturbo and convert to 100uV (mV -> 100uV) = mV*10 // Multiply by Vratio @@ -1244,7 +1169,7 @@ void calculate_ceff_ratio_vdd( void ) * @reasoncode DIVIDE_BY_ZERO_ERROR * @userdata1 0 * @userdata4 OCC_NO_EXTENDED_RC - * @devdesc Divide by zero error on ceff_vdd / ceff_tdp_vdd + * @devdesc Get ceff_tdp_vdd from OCCPPB */ errlHndl_t l_errl = createErrl( CALC_CEFF_RATIO_VDD, @@ -1356,7 +1281,7 @@ inline int32_t interpolate_linear( int32_t i_X, * * Return: The multiplier representing the temperature factor */ -int32_t calculate_multiplier( int32_t i_temp ) +uint32_t calculate_multiplier( int32_t i_temp ) { int mult_idx; @@ -1642,3 +1567,110 @@ void read_req_active_quads( void ) // Save number of on bits g_wof->num_active_quads = on_bits; } + +/** + * get_voltage_index + * + * Desctiption: Using the input voltage, returns the index to the lower bound + * of the two voltages surrounding the input voltage in + * G_iddq_voltages + * + * Param[in]: i_voltage - the input voltage to select the index for + * + * Return: The index to the lower bound voltage in G_iddq_voltages + */ +int get_voltage_index( uint32_t i_voltage ) +{ + + int l_volt_idx; + if( i_voltage <= G_iddq_voltages[0] ) + { + // Voltage is <= to first entry. Use first two entries. + l_volt_idx = 0; + } + else if( i_voltage >= G_iddq_voltages[CORE_IDDQ_MEASUREMENTS-1] ) + { + // Voltage is >= to last entry. Use last two entries. + l_volt_idx = CORE_IDDQ_MEASUREMENTS - 2; + } + else + { + // Search for entries on either side of our voltage + for(l_volt_idx = 0; l_volt_idx < CORE_IDDQ_MEASUREMENTS - 1; l_volt_idx++) + { + if( (i_voltage >= G_iddq_voltages[l_volt_idx]) && + (i_voltage <= G_iddq_voltages[l_volt_idx+1]) ) + { + break; + } + } + } + return l_volt_idx; +} + +/** + * scale + * + * Description: Performs i_current*IDDQ_TEMP_FACTOR^(i_delta_temp)/10 + * where IDDQ_TEMP_FACTOR == 1.3 + * Note: The calculation is performed by doing a lookup + * in G_wof_iddq_mult_table based on the passed in delta temp. + * + * Param[in]: i_current - The current to scale + * Param[in]: i_delta_temp - The measured temperature - the temperature at which + * the input current was measured. + * Return: The scaled current + */ +uint32_t scale( uint16_t i_current, + int16_t i_delta_temp ) +{ + // Calculate the multipliers for the leakage current using the delta temp + uint32_t leak_multiplier = calculate_multiplier( i_delta_temp ); + // Scale the current and return + return (i_current * leak_multiplier) >> 10; +} + +/** + * scale_and_interpolate + * + * Desctiption: This function combines the scale and interpolate_linear + * functions in order to approximate a current based off the + * voltage scaled to the measured temperature (base temp) + * + * Param[in]: i_leak_arr - Array of IQ Currents taken from vpd (OCC Pstate + * parameter block. + * Param[in]: i_avgtemp_arr - Array of temperatures in which the currents + * in i_leak_arr were measured. Also taken from vpd. + * Param[in]: i_idx - The index into the two arrays calculated from voltage + * Param[in]: i_base_temp - The base temperature used to scale the current + * Param[in]: i_voltage - The associated voltage. + * + * Return: The approximated scaled current. + */ +uint32_t scale_and_interpolate( uint16_t * i_leak_arr, + uint8_t * i_avgtemp_arr, + int i_idx, + uint16_t i_base_temp, + uint16_t i_voltage ) +{ + // Calculate the Delta temps for the upper and lower bounds + // Note: avgtemp arrays are in 0.5C. Divide by 2 to convert + // to 1C + int16_t lower_delta = i_base_temp - (i_avgtemp_arr[i_idx] >> 1); + int16_t upper_delta = i_base_temp - (i_avgtemp_arr[i_idx+1] >> 1); + + // Scale the currents based on the delta temperature + uint32_t scaled_lower_leak = scale( i_leak_arr[i_idx], + lower_delta ); + uint32_t scaled_upper_leak = scale( i_leak_arr[i_idx], + upper_delta ); + + // Approximate current between the scaled currents using linear + // interpolation and return the result + return interpolate_linear( (int32_t) i_voltage, + (int32_t) G_iddq_voltages[i_idx], + (int32_t) G_iddq_voltages[i_idx+1], + (int32_t) scaled_lower_leak, + (int32_t) scaled_upper_leak ); + +} diff --git a/src/occ_405/wof/wof.h b/src/occ_405/wof/wof.h index b02f6c0..5008084 100644 --- a/src/occ_405/wof/wof.h +++ b/src/occ_405/wof/wof.h @@ -38,6 +38,7 @@ #define QUAD_POWERED_OFF 0xFF #define PGPE_WOF_OFF 0 #define PGPE_WOF_ON 1 +#define NUM_CORES_PER_QUAD 4 //****************************************************************************** // Bit Vector Masks //****************************************************************************** @@ -178,6 +179,8 @@ typedef struct uint16_t voltvdn_sensor; // Array to hold the current 1-byte pstate values read from SRAM. 0xFF=off uint8_t quad_x_pstates[MAXIMUM_QUADS]; + // Array to hold the voltage index for the quads based on their voltage + uint8_t quad_v_idx[MAXIMUM_QUADS]; // Bit vector to hold the ivrm states of the quads. 0=BYPASS, 1=REGULATION uint8_t quad_ivrm_states; // Contains the estimated core leakage based on temp, voltage, and vpd-leak @@ -192,8 +195,6 @@ typedef struct 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 @@ -215,40 +216,19 @@ typedef struct // 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; + uint8_t chip_volt_idx; // Contains the final calculated value of ALL_CORES_OFF_ISO uint32_t all_cores_off_iso; - // Contains the final calculated value of ALL_CACHES_ON_ISO - uint32_t all_caches_on_iso; + // Contains the final calculated value of ALL_GOOD_CACHES_ON_ISO + uint32_t all_good_caches_on_iso; + // Contains the final calculated value of ALL_CACHES_OFF_ISO + uint32_t all_caches_off_iso; // Contains good_cores_only (per_quad) - uint16_t quad_good_cores_only[MAXIMUM_QUADS]; + uint32_t quad_good_cores_only[MAXIMUM_QUADS]; // Contains on_cores uint16_t quad_on_cores[MAXIMUM_QUADS]; // Contains BAD_OFF_cores uint16_t quad_bad_off_cores[MAXIMUM_QUADS]; - // Contains the multiplier(m) used in y ~=(T*m)>>10 for nest leak calc - uint32_t nest_mult; - // Contains the multiplier(m) used in y ~=(T*m)>>10 for core leak calc 0-23 - uint32_t core_mult[MAX_NUM_CORES]; - // Contains the multiplier(m) used in y ~=(T*m)>>10 for quad leak calc 0-5 - uint32_t quad_mult[MAXIMUM_QUADS]; - // Contains the delta temp used for nest leakage calc (see G_wof_iddq_mult_table) - // TEMPNEST - tvpd_leak_off - int16_t nest_delta_temp; - // Contains the delta temp used for core leakage calc - // TEMPPROCTHRMy - tvpd_leak_on (where y is the core number) - int16_t core_delta_temp[MAX_NUM_CORES]; - // Contains the delta temp used for quad leakage calc - // TEMPQx - tvpd_leak_cache (where x is the quad number) - int16_t quad_delta_temp[MAXIMUM_QUADS]; - // tvpd leak to use when either the core is off, or the entire quad is off - uint32_t tvpd_leak_off; - // tvpd leak to use when the core is on - uint32_t tvpd_leak_on; - // tvpd leak to use when performing cache calculations - uint32_t tvpd_leak_cache; - // tvpd leak used for nest leakage calculations - uint32_t tvpd_leak_nest; // Contains the most recently read value from SRAM for Requested active quads // Value represents a bit vector denoting which quads are active uint8_t req_active_quad_update; @@ -280,6 +260,8 @@ typedef struct uint32_t pgpe_wof_state_addr; // The address in shared OCC-PGPE SRAM of the Requested Active quads uint32_t req_active_quads_addr; + // The core leakage percent portion of VDD + uint16_t core_leakage_percent; } amec_wof_t; typedef struct @@ -344,13 +326,12 @@ inline int32_t interpolate_linear( int32_t i_X, int32_t i_y1, int32_t i_y2 ); -int32_t calculate_multiplier( int32_t i_temp ); +uint32_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 ); void disable_wof( void ); @@ -362,4 +343,15 @@ void wof_control_callback( void ); void send_initial_vfrt_to_pgpe( void ); void read_req_active_quads( void ); + +int get_voltage_index( uint32_t i_voltage ); + +uint32_t scale( uint16_t i_current, + int16_t i_delta_temp ); + +uint32_t scale_and_interpolate( uint16_t * i_leak_arr, + uint8_t * i_avgtemp_arr, + int i_idx, + uint16_t i_base_temp, + uint16_t i_voltage ); #endif |