summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndres Lugo-Reyes <aalugore@us.ibm.com>2017-04-27 13:59:38 -0500
committerMartha Broyles <mbroyles@us.ibm.com>2017-05-17 14:08:29 -0400
commita64c253aa40eb0aba7f3fa6d6ee5f5cec93cc66e (patch)
tree07a1c2e0e0cb2587dc028007ef8fa62b71072e70 /src
parent8a7df03ba3d475d51f8507a0424b63868cca7e8a (diff)
downloadtalos-occ-a64c253aa40eb0aba7f3fa6d6ee5f5cec93cc66e.tar.gz
talos-occ-a64c253aa40eb0aba7f3fa6d6ee5f5cec93cc66e.zip
WOF: Change leakage calculation algorithms
The previous version of the leakage calculations only scaled the final calculated value. This has now been updated to scale all leakage currents as soon as they are read out of the OPPB. Change-Id: I978ddd4e1dd8df615a89c454eeddd8f4f34209b9 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/39516 Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/include/p9_pstates_common.h203
-rw-r--r--src/include/p9_pstates_occ.h33
-rw-r--r--src/include/pstate_pgpe_occ_api.h4
-rwxr-xr-xsrc/occ_405/amec/amec_parm.h15
-rwxr-xr-xsrc/occ_405/amec/amec_parm_table.c19
-rw-r--r--src/occ_405/wof/wof.c448
-rw-r--r--src/occ_405/wof/wof.h54
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
OpenPOWER on IntegriCloud