summaryrefslogtreecommitdiffstats
path: root/src/occ_405
diff options
context:
space:
mode:
Diffstat (limited to 'src/occ_405')
-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
4 files changed, 273 insertions, 263 deletions
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