| /* |
| * Copyright (c) 2011 Massachusetts Institute of Technology |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * Authors: Konstantinos Aisopos |
| */ |
| |
| /* |
| * Official Tool Website: www.mit.edu/~kaisopos/FaultModel |
| * |
| * If you use our tool for academic research, we request that you cite: |
| * Konstantinos Aisopos, Chia-Hsin Owen Chen, and Li-Shiuan Peh. Enabling |
| * System-Level Modeling of Variation-Induced Faults in Networks-on-Chip. |
| * Proceedings of the 48th Design Automation Conference (DAC'11) |
| */ |
| |
| // C++ includes |
| #include <cassert> |
| #include <fstream> |
| #include <iostream> |
| #include <vector> |
| |
| // GEM5 includes |
| #include "FaultModel.hh" |
| #include "base/logging.hh" |
| |
| using namespace std; |
| |
| #define MAX(a,b) ((a > b) ? (a) : (b)) |
| |
| |
| FaultModel::FaultModel(const Params *p) : SimObject(p) |
| { |
| // read configurations into "configurations" vector |
| // format: <buff/vc> <vcs> <10 fault types> |
| bool more_records = true; |
| for (int i = 0; more_records; i += (fields_per_conf_record)){ |
| system_conf configuration; |
| configuration.buff_per_vc = |
| p->baseline_fault_vector_database[i + conf_record_buff_per_vc]; |
| configuration.vcs = |
| p->baseline_fault_vector_database[i + conf_record_vcs]; |
| for (int fault_index = 0; fault_index < number_of_fault_types; |
| fault_index++){ |
| configuration.fault_type[fault_index] = |
| p->baseline_fault_vector_database[i + |
| conf_record_first_fault_type + fault_index] / 100; |
| } |
| configurations.push_back(configuration); |
| if (p->baseline_fault_vector_database[i+fields_per_conf_record] < 0){ |
| more_records = false; |
| } |
| } |
| |
| // read temperature weights into "temperature_weights" vector |
| // format: <temperature> <weight> |
| more_records = true; |
| for (int i = 0; more_records; i += (fields_per_temperature_record)){ |
| int record_temperature = |
| p->temperature_weights_database[i + temperature_record_temp]; |
| int record_weight = |
| p->temperature_weights_database[i + temperature_record_weight]; |
| static int first_record = true; |
| if (first_record){ |
| for (int temperature = 0; temperature < record_temperature; |
| temperature++){ |
| temperature_weights.push_back(0); |
| } |
| first_record = false; |
| } |
| assert(record_temperature == temperature_weights.size()); |
| temperature_weights.push_back(record_weight); |
| if (p->temperature_weights_database[i + |
| fields_per_temperature_record] < 0){ |
| more_records = false; |
| } |
| } |
| } |
| |
| string |
| FaultModel::fault_type_to_string(int ft) |
| { |
| if (ft == data_corruption__few_bits){ |
| return "data_corruption__few_bits"; |
| } else if (ft == data_corruption__all_bits){ |
| return "data_corruption__all_bits"; |
| } else if (ft == flit_conservation__flit_duplication){ |
| return "flit_conservation__flit_duplication"; |
| } else if (ft == flit_conservation__flit_loss_or_split){ |
| return "flit_conservation__flit_loss_or_split"; |
| } else if (ft == misrouting){ |
| return "misrouting"; |
| } else if (ft == credit_conservation__credit_generation){ |
| return "credit_conservation__credit_generation"; |
| } else if (ft == credit_conservation__credit_loss){ |
| return "credit_conservation__credit_loss"; |
| } else if (ft == erroneous_allocation__VC){ |
| return "erroneous_allocation__VC"; |
| } else if (ft == erroneous_allocation__switch){ |
| return "erroneous_allocation__switch"; |
| } else if (ft == unfair_arbitration){ |
| return "unfair_arbitration"; |
| } else if (ft == number_of_fault_types){ |
| return "none"; |
| } else { |
| return "none"; |
| } |
| } |
| |
| |
| int |
| FaultModel::declare_router(int number_of_inputs, |
| int number_of_outputs, |
| int number_of_vcs_per_input, |
| int number_of_buff_per_data_vc, |
| int number_of_buff_per_ctrl_vc) |
| { |
| // check inputs (are they legal?) |
| if (number_of_inputs <= 0 || number_of_outputs <= 0 || |
| number_of_vcs_per_input <= 0 || number_of_buff_per_data_vc <= 0 || |
| number_of_buff_per_ctrl_vc <= 0){ |
| fatal("Fault Model: ERROR in argument of FaultModel_declare_router!"); |
| } |
| int number_of_buffers_per_vc = MAX(number_of_buff_per_data_vc, |
| number_of_buff_per_ctrl_vc); |
| int total_vcs = number_of_inputs * number_of_vcs_per_input; |
| if (total_vcs > MAX_VCs){ |
| fatal("Fault Model: ERROR! Number inputs*VCs (MAX_VCs) unsupported"); |
| } |
| if (number_of_buffers_per_vc > MAX_BUFFERS_per_VC){ |
| fatal("Fault Model: ERROR! buffers/VC (MAX_BUFFERS_per_VC) too high"); |
| } |
| |
| // link the router to a DB record |
| int record_hit = -1; |
| for (int record = 0; record < configurations.size(); record++){ |
| if ((configurations[record].buff_per_vc == number_of_buffers_per_vc)&& |
| (configurations[record].vcs == total_vcs)){ |
| record_hit = record; |
| } |
| } |
| if (record_hit == -1){ |
| panic("Fault Model: ERROR! configuration not found in DB. BUG?"); |
| } |
| |
| // remember the router and return its ID |
| routers.push_back(configurations[record_hit]); |
| static int router_index = 0; |
| return router_index++; |
| } |
| |
| bool |
| FaultModel::fault_vector(int routerID, |
| int temperature_input, |
| float fault_vector[]) |
| { |
| bool ok = true; |
| |
| // is the routerID recorded? |
| if (routerID < 0 || routerID >= ((int) routers.size())){ |
| warn("Fault Model: ERROR! unknown router ID argument."); |
| fatal("Fault Model: Did you enable the fault model flag)?"); |
| } |
| |
| // is the temperature too high/too low? |
| int temperature = temperature_input; |
| if (temperature_input >= ((int) temperature_weights.size())){ |
| ok = false; |
| warn_once("Fault Model: Temperature exceeded simulated upper bound."); |
| warn_once("Fault Model: The fault model is not accurate any more."); |
| temperature = (temperature_weights.size() - 1); |
| } else if (temperature_input < 0){ |
| ok = false; |
| warn_once("Fault Model: Temperature exceeded simulated lower bound."); |
| warn_once("Fault Model: The fault model is not accurate any more."); |
| temperature = 0; |
| } |
| |
| // recover the router record and return its fault vector |
| for (int i = 0; i < number_of_fault_types; i++){ |
| fault_vector[i] = routers[routerID].fault_type[i] * |
| ((float)temperature_weights[temperature]); |
| } |
| return ok; |
| } |
| |
| bool |
| FaultModel::fault_prob(int routerID, |
| int temperature_input, |
| float *aggregate_fault_prob) |
| { |
| *aggregate_fault_prob = 1.0; |
| bool ok = true; |
| |
| // is the routerID recorded? |
| if (routerID < 0 || routerID >= ((int) routers.size())){ |
| warn("Fault Model: ERROR! unknown router ID argument."); |
| fatal("Fault Model: Did you enable the fault model flag)?"); |
| } |
| |
| // is the temperature too high/too low? |
| int temperature = temperature_input; |
| if (temperature_input >= ((int) temperature_weights.size()) ){ |
| ok = false; |
| warn_once("Fault Model: Temperature exceeded simulated upper bound."); |
| warn_once("Fault Model: The fault model is not accurate any more."); |
| temperature = (temperature_weights.size()-1); |
| } else if (temperature_input < 0){ |
| ok = false; |
| warn_once("Fault Model: Temperature exceeded simulated lower bound."); |
| warn_once("Fault Model: The fault model is not accurate any more."); |
| temperature = 0; |
| } |
| |
| // recover the router record and return its aggregate fault probability |
| for (int i = 0; i < number_of_fault_types; i++){ |
| *aggregate_fault_prob= *aggregate_fault_prob * |
| ( 1.0 - (routers[routerID].fault_type[i] * |
| ((float)temperature_weights[temperature])) ); |
| } |
| *aggregate_fault_prob = 1.0 - *aggregate_fault_prob; |
| return ok; |
| } |
| |
| // this function is used only for debugging purposes |
| void |
| FaultModel::print(void) |
| { |
| cout << "--- PRINTING configurations ---\n"; |
| for (int record = 0; record < configurations.size(); record++){ |
| cout << "(" << record << ") "; |
| cout << "VCs=" << configurations[record].vcs << " "; |
| cout << "Buff/VC=" << configurations[record].buff_per_vc << " ["; |
| for (int fault_type_num = 0; |
| fault_type_num < number_of_fault_types; |
| fault_type_num++){ |
| cout << (100 * configurations[record].fault_type[fault_type_num]); |
| cout << "% "; |
| } |
| cout << "]\n"; |
| } |
| cout << "--- PRINTING temperature weights ---\n"; |
| for (int record = 0; record < temperature_weights.size(); record++){ |
| cout << "temperature=" << record << " => "; |
| cout << "weight=" << temperature_weights[record]; |
| cout << "\n"; |
| } |
| } |
| |
| FaultModel * |
| FaultModelParams::create() |
| { |
| return new FaultModel(this); |
| } |