/************************* INCLUDES *********************************/ #include #include #include #include using namespace std; #include #include "util.h" #include "PowerSpicedComponent.h" PowerCallibInputs::PowerCallibInputs(PowerSpicedComponent * parent_, float inputs) : parent(parent_), num_inputs(inputs), sorted(false), done_callibration( false) { /* Add min/max bounding entries */ add_size(0); add_size(std::numeric_limits::max()); } void PowerCallibInputs::add_size(float transistor_size, float power) { PowerCallibSize * entry = new PowerCallibSize(transistor_size, power); entries.push_back(entry); sorted = false; } bool sorter_PowerCallibSize(PowerCallibSize * a, PowerCallibSize * b) { return a->transistor_size < b->transistor_size; } void PowerCallibInputs::sort_me() { sort(entries.begin(), entries.end(), sorter_PowerCallibSize); sorted = true; } void PowerCallibInputs::callibrate() { assert(entries.size() >= 2); for (vector::iterator it = entries.begin() + 1; it != entries.end() - 1; it++) { float est_power = parent->component_usage(num_inputs, (*it)->transistor_size); (*it)->factor = (*it)->power / est_power; } /* Set min-value placeholder */ entries[0]->factor = entries[1]->factor; /* Set max-value placeholder */ entries[entries.size() - 1]->factor = entries[entries.size() - 2]->factor; done_callibration = true; } PowerCallibSize * PowerCallibInputs::get_entry_bound(bool lower, float transistor_size) { PowerCallibSize * prev = entries[0]; assert(sorted); for (vector::iterator it = entries.begin() + 1; it != entries.end(); it++) { if ((*it)->transistor_size > transistor_size) { if (lower) return prev; else return *it; } prev = *it; } return NULL; } PowerSpicedComponent::PowerSpicedComponent( float (*usage_fn)(int num_inputs, float transistor_size)) { component_usage = usage_fn; /* Always pad with a high and low entry */ add_entry(0); // add_entry(std::numeric_limits::max()); add_entry(1000000000); done_callibration = false; sorted = true; } PowerCallibInputs * PowerSpicedComponent::add_entry(int num_inputs) { PowerCallibInputs * entry = new PowerCallibInputs(this, num_inputs); entries.push_back(entry); return entry; } PowerCallibInputs * PowerSpicedComponent::get_entry(int num_inputs) { vector::iterator it; for (it = entries.begin(); it != entries.end(); it++) { if ((*it)->num_inputs == num_inputs) { break; } } if (it == entries.end()) { return add_entry(num_inputs); } else { return *it; } } PowerCallibInputs * PowerSpicedComponent::get_entry_bound(bool lower, int num_inputs) { PowerCallibInputs * prev = entries[0]; assert(sorted); for (vector::iterator it = entries.begin() + 1; it != entries.end(); it++) { if ((*it)->num_inputs > num_inputs) { if (lower) { if (prev == entries[0]) return NULL; else return prev; } else { if (*it == entries[entries.size() - 1]) return NULL; else return *it; } } prev = *it; } return NULL; } void PowerSpicedComponent::add_data_point(int num_inputs, float transistor_size, float power) { assert(!done_callibration); PowerCallibInputs * inputs_entry = get_entry(num_inputs); inputs_entry->add_size(transistor_size, power); sorted = false; } float PowerSpicedComponent::scale_factor(int num_inputs, float transistor_size) { PowerCallibInputs * inputs_lower; PowerCallibInputs * inputs_upper; PowerCallibSize * size_lower; PowerCallibSize * size_upper; float factor_lower = 0.; float factor_upper = 0.; float factor; float perc_upper; assert(done_callibration); inputs_lower = get_entry_bound(true, num_inputs); inputs_upper = get_entry_bound(false, num_inputs); if (inputs_lower) { /* Interpolation of factor between sizes for lower # inputs */ assert(inputs_lower->done_callibration); size_lower = inputs_lower->get_entry_bound(true, transistor_size); size_upper = inputs_lower->get_entry_bound(false, transistor_size); perc_upper = (transistor_size - size_lower->transistor_size) / (size_upper->transistor_size - size_lower->transistor_size); factor_lower = perc_upper * size_upper->factor + (1 - perc_upper) * size_lower->factor; } if (inputs_upper) { /* Interpolation of factor between sizes for upper # inputs */ assert(inputs_upper->done_callibration); size_lower = inputs_upper->get_entry_bound(true, transistor_size); size_upper = inputs_upper->get_entry_bound(false, transistor_size); perc_upper = (transistor_size - size_lower->transistor_size) / (size_upper->transistor_size - size_lower->transistor_size); factor_upper = perc_upper * size_upper->factor + (1 - perc_upper) * size_lower->factor; } if (!inputs_lower) { factor = factor_upper; } else if (!inputs_upper) { factor = factor_lower; } else { /* Interpolation of factor between inputs */ perc_upper = ((float) (num_inputs - inputs_lower->num_inputs)) / ((float) (inputs_upper->num_inputs - inputs_lower->num_inputs)); factor = perc_upper * factor_upper + (1 - perc_upper) * factor_lower; } return factor; } bool sorter_PowerCallibInputs(PowerCallibInputs * a, PowerCallibInputs * b) { return a->num_inputs < b->num_inputs; } void PowerSpicedComponent::sort_me(void) { sort(entries.begin(), entries.end(), sorter_PowerCallibInputs); for (vector::iterator it = entries.begin(); it != entries.end(); it++) { (*it)->sort_me(); } sorted = true; } void PowerSpicedComponent::callibrate(void) { sort_me(); for (vector::iterator it = entries.begin(); it != entries.end(); it++) { (*it)->callibrate(); } done_callibration = true; } bool PowerSpicedComponent::is_done_callibration(void) { return done_callibration; }