GARNET: adding a fault model for resilient on-chip network research.
authorTushar Krishna <tushar@csail.mit.edu>
Fri, 4 Nov 2011 22:40:22 +0000 (18:40 -0400)
committerTushar Krishna <tushar@csail.mit.edu>
Fri, 4 Nov 2011 22:40:22 +0000 (18:40 -0400)
This patch adds a fault model, which provides the probability of a number of
architectural faults in the interconnection network (e.g., data corruption,
misrouting). These probabilities can be used to realistically inject faults
in GARNET and faithfully evaluate the effectiveness of novel resilient NoC
architectures.

12 files changed:
configs/ruby/Ruby.py
src/mem/ruby/network/fault_model/FaultModel.cc [new file with mode: 0644]
src/mem/ruby/network/fault_model/FaultModel.hh [new file with mode: 0644]
src/mem/ruby/network/fault_model/FaultModel.py [new file with mode: 0644]
src/mem/ruby/network/fault_model/SConscript [new file with mode: 0644]
src/mem/ruby/network/garnet/BaseGarnetNetwork.cc
src/mem/ruby/network/garnet/BaseGarnetNetwork.hh
src/mem/ruby/network/garnet/BaseGarnetNetwork.py
src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc
src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh
src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc
src/mem/ruby/network/garnet/fixed-pipeline/Router_d.hh

index 9174709b48b677603f21f688c9cb72ca9fcabb4b..e83e7f23f442d5c3c0c88605fdef571dd2758245 100644 (file)
@@ -40,6 +40,8 @@ def define_options(parser):
                       help="the number of rows in the mesh topology")
     parser.add_option("--garnet-network", type="string", default=None,
                       help="'fixed'|'flexible'")
+    parser.add_option("--network-fault-model", action="store_true", default=False,
+                      help="enable network fault model: see src/mem/ruby/network/fault_model/")
 
     # ruby mapping options
     parser.add_option("--numa-high-bit", type="int", default=0,
@@ -109,7 +111,13 @@ def create_system(options, system, piobus = None, dma_devices = []):
         print "Error: could not create topology %s" % options.topology
         raise
 
-    network = NetworkClass(ruby_system = ruby, topology = net_topology)
+    if options.network_fault_model:
+        assert(options.garnet_network == "fixed")
+        fault_model = FaultModel()
+        network = NetworkClass(ruby_system = ruby, topology = net_topology,\
+                               enable_fault_model=True, fault_model = fault_model)
+    else:
+        network = NetworkClass(ruby_system = ruby, topology = net_topology)
 
     #
     # Loop through the directory controlers.
diff --git a/src/mem/ruby/network/fault_model/FaultModel.cc b/src/mem/ruby/network/fault_model/FaultModel.cc
new file mode 100644 (file)
index 0000000..195f7c6
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * 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 <assert.h>
+#include <stdio.h>
+
+// C++ includes
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+// GEM5 includes
+#include "FaultModel.hh"
+#include "base/misc.hh" 
+
+#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);
+}
diff --git a/src/mem/ruby/network/fault_model/FaultModel.hh b/src/mem/ruby/network/fault_model/FaultModel.hh
new file mode 100644 (file)
index 0000000..12a3f38
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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)
+ */
+
+#ifndef __MEM_RUBY_NETWORK_FAULT_MODEL_HH__
+#define __MEM_RUBY_NETWORK_FAULT_MODEL_HH__
+
+// tool limitations and fixed inputs
+#define MAX_VCs 40
+#define MAX_BUFFERS_per_VC 5
+#define BASELINE_TEMPERATURE_CELCIUS 71
+
+// C++ includes
+#include <string>
+using namespace std;
+
+// GEM5 includes
+#include "params/FaultModel.hh"
+#include "sim/sim_object.hh"
+
+class FaultModel : public SimObject
+{
+  public:
+    typedef FaultModelParams Params;
+    FaultModel(const Params *p);
+    const Params *params() const { return (const Params *)_params; }
+
+    /************************************************************************/
+    /**********  THE FAULT TYPES SUPPORTED BY THE FAULT MODEL ***************/
+    /************************************************************************/
+
+    enum fault_type 
+    {
+        data_corruption__few_bits,
+        data_corruption__all_bits,
+        flit_conservation__flit_duplication,
+        flit_conservation__flit_loss_or_split,
+        misrouting,
+        credit_conservation__credit_generation,
+        credit_conservation__credit_loss,
+        erroneous_allocation__VC,
+        erroneous_allocation__switch,
+        unfair_arbitration,
+        number_of_fault_types
+    };
+
+    /************************************************************************/
+    /********************  INTERFACE OF THE FAULT MODEL *********************/
+    /************************************************************************/
+
+    enum conf_record_format
+    {
+        conf_record_buff_per_vc,
+        conf_record_vcs,
+        conf_record_first_fault_type,
+        conf_record_last_fault_type = conf_record_first_fault_type + number_of_fault_types - 1,
+        fields_per_conf_record
+    };
+
+    enum temperature_record_format
+    {
+        temperature_record_temp,
+        temperature_record_weight,
+        fields_per_temperature_record
+    };
+
+    struct system_conf
+    {
+        int vcs;
+        int buff_per_vc;
+        float fault_type[number_of_fault_types];
+    };
+
+    int declare_router(int number_of_inputs, 
+                       int number_of_outputs, 
+                       int number_of_vcs_per_vnet, 
+                       int number_of_buff_per_data_vc, 
+                       int number_of_buff_per_ctrl_vc);
+
+    string fault_type_to_string(int fault_type_index);
+    // the following 2 functions are called at runtime, to get the probability 
+    // of each fault type (fault_vector) or the aggregate fault probability 
+    // (fault_prob). Note: the probability values are provided by reference
+    // (in the variables fault_vector[] & aggregate_fault_prob respectively).
+    // Both functions also return a success flag (which is always true if 
+    // temperature ranges from 0C to 125C)
+
+    bool fault_vector(int routerID, 
+                      int temperature, 
+                      float fault_vector[]);
+
+    bool fault_prob(int routerID,
+                    int temperature, 
+                    float *aggregate_fault_prob);
+
+    // for debugging purposes
+
+    void print(void);
+
+  private:
+    vector <system_conf> configurations;
+    vector <system_conf> routers;
+    vector <int> temperature_weights;
+};
+
+#endif //  __MEM_RUBY_NETWORK_FAULT_MODEL_HH__
diff --git a/src/mem/ruby/network/fault_model/FaultModel.py b/src/mem/ruby/network/fault_model/FaultModel.py
new file mode 100644 (file)
index 0000000..5117491
--- /dev/null
@@ -0,0 +1,302 @@
+# 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)
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+class FaultModel(SimObject):
+    type = 'FaultModel'
+    cxx_class = 'FaultModel' 
+    
+    baseline_fault_vector_database = VectorParam.Float([
+        5, 40, 0.080892, 0.109175, 0.018864, 0.130408, 0.059724, 0.077571, 0.034830, 0.083430, 0.067500, 0.121500,
+        5, 39, 0.062640, 0.089100, 0.016821, 0.109620, 0.051462, 0.060210, 0.029700, 0.076140, 0.062100, 0.116100,
+        5, 38, 0.050490, 0.076950, 0.015782, 0.091530, 0.044550, 0.046170, 0.025920, 0.070200, 0.057294, 0.110700,
+        5, 37, 0.042120, 0.067770, 0.014191, 0.082890, 0.040986, 0.037800, 0.023760, 0.065880, 0.053568, 0.104490,
+        5, 36, 0.035910, 0.061020, 0.013211, 0.075600, 0.035100, 0.030240, 0.021060, 0.061560, 0.049815, 0.100710,
+        5, 35, 0.032130, 0.054810, 0.011964, 0.071550, 0.031860, 0.026730, 0.019710, 0.057510, 0.047169, 0.094230,
+        5, 34, 0.028890, 0.051030, 0.011054, 0.067500, 0.030510, 0.023450, 0.018630, 0.054000, 0.045900, 0.088290,
+        5, 33, 0.026460, 0.047250, 0.010160, 0.062640, 0.028971, 0.021600, 0.017280, 0.049410, 0.042903, 0.082080,
+        5, 32, 0.024300, 0.042930, 0.009312, 0.057780, 0.027000, 0.019710, 0.016470, 0.045360, 0.041310, 0.075600,
+        5, 31, 0.022410, 0.037260, 0.008910, 0.054540, 0.024732, 0.018171, 0.015660, 0.043470, 0.039447, 0.070740,
+        5, 30, 0.021870, 0.032130, 0.008162, 0.050220, 0.023625, 0.016762, 0.013770, 0.039150, 0.037557, 0.065880,
+        5, 29, 0.020790, 0.028080, 0.007657, 0.042660, 0.020061, 0.016043, 0.012690, 0.036720, 0.035451, 0.062370,
+        5, 28, 0.019440, 0.025650, 0.007123, 0.037800, 0.018900, 0.015363, 0.011880, 0.033480, 0.032400, 0.057780,
+        5, 27, 0.018473, 0.023760, 0.006737, 0.034830, 0.018036, 0.014153, 0.011232, 0.030240, 0.030645, 0.055890,
+        5, 26, 0.017550, 0.021330, 0.006440, 0.032130, 0.016497, 0.013511, 0.010031, 0.027621, 0.028242, 0.051030,
+        5, 25, 0.016462, 0.020520, 0.006210, 0.028890, 0.015822, 0.013095, 0.009442, 0.021600, 0.026379, 0.046170,
+        5, 24, 0.015930, 0.018360, 0.005940, 0.026730, 0.015047, 0.012377, 0.008918, 0.018360, 0.023193, 0.037800,
+        5, 23, 0.015390, 0.017931, 0.005594, 0.025488, 0.013365, 0.012037, 0.008775, 0.015120, 0.018657, 0.031590,
+        5, 22, 0.014804, 0.017167, 0.005338, 0.023976, 0.012258, 0.011734, 0.008087, 0.013500, 0.015444, 0.026190,
+        5, 21, 0.014180, 0.016548, 0.004995, 0.022194, 0.011807, 0.011073, 0.007236, 0.011070, 0.013500, 0.021870,
+        5, 20, 0.013743, 0.016176, 0.004613, 0.020414, 0.011070, 0.010415, 0.006220, 0.010415, 0.010800, 0.019077,
+        5, 19, 0.011877, 0.015412, 0.003861, 0.016659, 0.008235, 0.008640, 0.005400, 0.009720, 0.008532, 0.013770,
+        5, 18, 0.011097, 0.014310, 0.003483, 0.014526, 0.006912, 0.007560, 0.003780, 0.008640, 0.006885, 0.010260,
+        5, 17, 0.010419, 0.011939, 0.002700, 0.011394, 0.005400, 0.006318, 0.003038, 0.008100, 0.005400, 0.009450,
+        5, 16, 0.009887, 0.009720, 0.002395, 0.010152, 0.004023, 0.005400, 0.002743, 0.007020, 0.004590, 0.008370,
+        5, 15, 0.009617, 0.007825, 0.002079, 0.008289, 0.003780, 0.004806, 0.002236, 0.006480, 0.003996, 0.008127,
+        5, 14, 0.008710, 0.006820, 0.001817, 0.007749, 0.003240, 0.004185, 0.001760, 0.005400, 0.002538, 0.006615,
+        5, 13, 0.008116, 0.006566, 0.001566, 0.006426, 0.002741, 0.003564, 0.001299, 0.004590, 0.001917, 0.005994,
+        5, 12, 0.007908, 0.006151, 0.001350, 0.005400, 0.002471, 0.003132, 0.000794, 0.004050, 0.001323, 0.005940,
+        5, 11, 0.007690, 0.005627, 0.001094, 0.005076, 0.002363, 0.002052, 0.000567, 0.003510, 0.001188, 0.004860,
+        5, 10, 0.007560, 0.005038, 0.000805, 0.004536, 0.001985, 0.000540, 0.000000, 0.002430, 0.000999, 0.003240,
+        5, 9, 0.007314, 0.004193, 0.000540, 0.003834, 0.001715, 0.000000, 0.000000, 0.002160, 0.000945, 0.002700,
+        5, 8, 0.006750, 0.003240, 0.000000, 0.003240, 0.001323, 0.000000, 0.000000, 0.001350, 0.000837, 0.002646,
+        5, 7, 0.006461, 0.002700, 0.000000, 0.002700, 0.001215, 0.000000, 0.000000, 0.000000, 0.000810, 0.001809,
+        5, 6, 0.006240, 0.001796, 0.000000, 0.002052, 0.001013, 0.000000, 0.000000, 0.000000, 0.000756, 0.001620,
+        5, 5, 0.005430, 0.000675, 0.000000, 0.000864, 0.000864, 0.000000, 0.000000, 0.000000, 0.000729, 0.001593,
+        5, 4, 0.003780, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.001080,
+        5, 3, 0.001350, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000540,
+        5, 2, 0.000540, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000270,
+        5, 1, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        4, 40, 0.079484, 0.106785, 0.018198, 0.122699, 0.057538, 0.076974, 0.034813, 0.079276, 0.061426, 0.112509,
+        4, 39, 0.062146, 0.088671, 0.016205, 0.108082, 0.050454, 0.059905, 0.029600, 0.075465, 0.057362, 0.106596,
+        4, 38, 0.050047, 0.076478, 0.014924, 0.090994, 0.043475, 0.045808, 0.025794, 0.069220, 0.054351, 0.101993,
+        4, 37, 0.041712, 0.067272, 0.013551, 0.082516, 0.040026, 0.037390, 0.023580, 0.064897, 0.051395, 0.097511,
+        4, 36, 0.035384, 0.060487, 0.012434, 0.075287, 0.034229, 0.029784, 0.020859, 0.060167, 0.048222, 0.094055,
+        4, 35, 0.031455, 0.054259, 0.011290, 0.071141, 0.031259, 0.026055, 0.019560, 0.055478, 0.045887, 0.088965,
+        4, 34, 0.028307, 0.050427, 0.010342, 0.067048, 0.029835, 0.022525, 0.018495, 0.052523, 0.044253, 0.083727,
+        4, 33, 0.025847, 0.046687, 0.009384, 0.062196, 0.028000, 0.020646, 0.017102, 0.048735, 0.041837, 0.079286,
+        4, 32, 0.023688, 0.042449, 0.008645, 0.057303, 0.026070, 0.018765, 0.016315, 0.045001, 0.040163, 0.073143,
+        4, 31, 0.021905, 0.036781, 0.008235, 0.054011, 0.024200, 0.017496, 0.015528, 0.042795, 0.038273, 0.068675,
+        4, 30, 0.021195, 0.031563, 0.007456, 0.049545, 0.022757, 0.016081, 0.013646, 0.038817, 0.036410, 0.063086,
+        4, 29, 0.020115, 0.027494, 0.006992, 0.042302, 0.019517, 0.015096, 0.012562, 0.035562, 0.034223, 0.059954,
+        4, 28, 0.018889, 0.025040, 0.006472, 0.037295, 0.018383, 0.014540, 0.011760, 0.032949, 0.032022, 0.055782,
+        4, 27, 0.017630, 0.023150, 0.006055, 0.034262, 0.017183, 0.013759, 0.010949, 0.029876, 0.030294, 0.053339,
+        4, 26, 0.016875, 0.020762, 0.005743, 0.031664, 0.016002, 0.013123, 0.009740, 0.026487, 0.027824, 0.048681,
+        4, 25, 0.015930, 0.019660, 0.005516, 0.028215, 0.015147, 0.012420, 0.009311, 0.020643, 0.025988, 0.043443,
+        4, 24, 0.015425, 0.017790, 0.005211, 0.026190, 0.014530, 0.011838, 0.008783, 0.017314, 0.022518, 0.035681,
+        4, 23, 0.014947, 0.017314, 0.004878, 0.024813, 0.012897, 0.011507, 0.008451, 0.014445, 0.017982, 0.029673,
+        4, 22, 0.014430, 0.016278, 0.004610, 0.023077, 0.011945, 0.011148, 0.007918, 0.012825, 0.015107, 0.023814,
+        4, 21, 0.013643, 0.015699, 0.004320, 0.021686, 0.011598, 0.010383, 0.007113, 0.010395, 0.013176, 0.019197,
+        4, 20, 0.013023, 0.015244, 0.003995, 0.019155, 0.010935, 0.009227, 0.005914, 0.009227, 0.010665, 0.016234,
+        4, 19, 0.011185, 0.014467, 0.003186, 0.015718, 0.007822, 0.007965, 0.005273, 0.008374, 0.008262, 0.012623,
+        4, 18, 0.010399, 0.013419, 0.002808, 0.013696, 0.006681, 0.006885, 0.003579, 0.007579, 0.006197, 0.009315,
+        4, 17, 0.009773, 0.011089, 0.002025, 0.010882, 0.005054, 0.005881, 0.002928, 0.007101, 0.004914, 0.008100,
+        4, 16, 0.009054, 0.009054, 0.001743, 0.009477, 0.003799, 0.005081, 0.002365, 0.006345, 0.003942, 0.007061,
+        4, 15, 0.008575, 0.006882, 0.001404, 0.007792, 0.003449, 0.004131, 0.001793, 0.005327, 0.002903, 0.006264,
+        4, 14, 0.008069, 0.005655, 0.001169, 0.006920, 0.002808, 0.003510, 0.001277, 0.004307, 0.001782, 0.005184,
+        4, 13, 0.007668, 0.005173, 0.000986, 0.005751, 0.002336, 0.002889, 0.000919, 0.003609, 0.001283, 0.004631,
+        4, 12, 0.007403, 0.004563, 0.000675, 0.004852, 0.002066, 0.002457, 0.000532, 0.003083, 0.000662, 0.004374,
+        4, 11, 0.007152, 0.004127, 0.000547, 0.004401, 0.001937, 0.001377, 0.000284, 0.002473, 0.000594, 0.003456,
+        4, 10, 0.006885, 0.003530, 0.000402, 0.003920, 0.001613, 0.000405, 0.000000, 0.001755, 0.000500, 0.002565,
+        4, 9, 0.006746, 0.002920, 0.000270, 0.003159, 0.001404, 0.000000, 0.000000, 0.001485, 0.000473, 0.002025,
+        4, 8, 0.006257, 0.002290, 0.000000, 0.002565, 0.001107, 0.000000, 0.000000, 0.000675, 0.000419, 0.001971,
+        4, 7, 0.005931, 0.001825, 0.000000, 0.002025, 0.000999, 0.000000, 0.000000, 0.000000, 0.000405, 0.001134,
+        4, 6, 0.005585, 0.001199, 0.000000, 0.001463, 0.000844, 0.000000, 0.000000, 0.000000, 0.000378, 0.000945,
+        4, 5, 0.004967, 0.000545, 0.000000, 0.000637, 0.000695, 0.000000, 0.000000, 0.000000, 0.000405, 0.000864,
+        4, 4, 0.003105, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000540,
+        4, 3, 0.000888, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000270,
+        4, 2, 0.000270, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000135,
+        4, 1, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        3, 40, 0.078075, 0.104396, 0.017531, 0.114991, 0.055352, 0.076378, 0.034795, 0.075122, 0.055352, 0.103518,
+        3, 39, 0.061652, 0.088241, 0.015590, 0.106545, 0.049445, 0.059600, 0.029500, 0.074790, 0.052623, 0.097092,
+        3, 38, 0.049604, 0.076005, 0.014067, 0.090458, 0.042401, 0.045446, 0.025669, 0.068240, 0.051408, 0.093285,
+        3, 37, 0.041305, 0.066774, 0.012911, 0.082142, 0.039066, 0.036979, 0.023401, 0.063914, 0.049221, 0.090531,
+        3, 36, 0.034857, 0.059954, 0.011656, 0.074974, 0.033359, 0.029327, 0.020658, 0.058774, 0.046629, 0.087399,
+        3, 35, 0.030780, 0.053708, 0.010616, 0.070732, 0.030659, 0.025380, 0.019410, 0.053447, 0.044604, 0.083700,
+        3, 34, 0.027724, 0.049823, 0.009631, 0.066596, 0.029160, 0.021600, 0.018360, 0.051046, 0.042606, 0.079164,
+        3, 33, 0.025234, 0.046124, 0.008608, 0.061752, 0.027030, 0.019691, 0.016924, 0.048060, 0.040770, 0.076491,
+        3, 32, 0.023077, 0.041969, 0.007979, 0.056827, 0.025140, 0.017820, 0.016160, 0.044642, 0.039015, 0.070686,
+        3, 31, 0.021400, 0.036302, 0.007560, 0.053482, 0.023668, 0.016821, 0.015395, 0.042120, 0.037098, 0.066609,
+        3, 30, 0.020520, 0.030996, 0.006750, 0.048870, 0.021889, 0.015401, 0.013522, 0.038483, 0.035262, 0.060291,
+        3, 29, 0.019440, 0.026908, 0.006326, 0.041945, 0.018973, 0.014148, 0.012434, 0.034403, 0.032994, 0.057537,
+        3, 28, 0.018338, 0.024430, 0.005821, 0.036790, 0.017866, 0.013716, 0.011640, 0.032419, 0.031644, 0.053784,
+        3, 27, 0.016786, 0.022540, 0.005373, 0.033693, 0.016330, 0.013365, 0.010665, 0.029511, 0.029943, 0.050787,
+        3, 26, 0.016200, 0.020193, 0.005046, 0.031199, 0.015506, 0.012736, 0.009450, 0.025353, 0.027405, 0.046332,
+        3, 25, 0.015398, 0.018800, 0.004822, 0.027540, 0.014472, 0.011745, 0.009180, 0.019686, 0.025596, 0.040716,
+        3, 24, 0.014920, 0.017221, 0.004482, 0.025650, 0.014013, 0.011300, 0.008648, 0.016268, 0.021843, 0.033561,
+        3, 23, 0.014504, 0.016697, 0.004161, 0.024138, 0.012428, 0.010978, 0.008127, 0.013770, 0.017307, 0.027756,
+        3, 22, 0.014056, 0.015390, 0.003883, 0.022178, 0.011632, 0.010562, 0.007749, 0.012150, 0.014769, 0.021438,
+        3, 21, 0.013106, 0.014850, 0.003645, 0.021179, 0.011389, 0.009693, 0.006990, 0.009720, 0.012852, 0.016524,
+        3, 20, 0.012304, 0.014313, 0.003378, 0.017896, 0.010800, 0.008039, 0.005608, 0.008039, 0.010530, 0.013392,
+        3, 19, 0.010492, 0.013522, 0.002511, 0.014777, 0.007409, 0.007290, 0.005146, 0.007028, 0.007992, 0.011475,
+        3, 18, 0.009701, 0.012528, 0.002133, 0.012866, 0.006450, 0.006210, 0.003378, 0.006518, 0.005508, 0.008370,
+        3, 17, 0.009126, 0.010238, 0.001350, 0.010371, 0.004709, 0.005443, 0.002819, 0.006102, 0.004428, 0.006750,
+        3, 16, 0.008222, 0.008389, 0.001091, 0.008802, 0.003575, 0.004763, 0.001987, 0.005670, 0.003294, 0.005751,
+        3, 15, 0.007533, 0.005940, 0.000729, 0.007295, 0.003119, 0.003456, 0.001350, 0.004174, 0.001809, 0.004401,
+        3, 14, 0.007428, 0.004490, 0.000521, 0.006091, 0.002376, 0.002835, 0.000794, 0.003213, 0.001026, 0.003753,
+        3, 13, 0.007220, 0.003780, 0.000405, 0.005076, 0.001931, 0.002214, 0.000540, 0.002627, 0.000648, 0.003267,
+        3, 12, 0.006899, 0.002975, 0.000000, 0.004304, 0.001661, 0.001782, 0.000270, 0.002117, 0.000000, 0.002808,
+        3, 11, 0.006615, 0.002627, 0.000000, 0.003726, 0.001512, 0.000702, 0.000000, 0.001436, 0.000000, 0.002052,
+        3, 10, 0.006210, 0.002022, 0.000000, 0.003305, 0.001242, 0.000270, 0.000000, 0.001080, 0.000000, 0.001890,
+        3, 9, 0.006178, 0.001647, 0.000000, 0.002484, 0.001094, 0.000000, 0.000000, 0.000810, 0.000000, 0.001350,
+        3, 8, 0.005765, 0.001339, 0.000000, 0.001890, 0.000891, 0.000000, 0.000000, 0.000000, 0.000000, 0.001296,
+        3, 7, 0.005400, 0.000950, 0.000000, 0.001350, 0.000783, 0.000000, 0.000000, 0.000000, 0.000000, 0.000459,
+        3, 6, 0.004930, 0.000602, 0.000000, 0.000875, 0.000675, 0.000000, 0.000000, 0.000000, 0.000000, 0.000270,
+        3, 5, 0.004504, 0.000416, 0.000000, 0.000410, 0.000527, 0.000000, 0.000000, 0.000000, 0.000081, 0.000135,
+        3, 4, 0.002430, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        3, 3, 0.000427, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        3, 2, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        3, 1, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        2, 40, 0.077418, 0.103451, 0.016828, 0.109064, 0.054341, 0.075962, 0.034795, 0.075122, 0.051976, 0.081459,
+        2, 39, 0.060720, 0.087215, 0.014756, 0.103532, 0.048041, 0.059297, 0.029376, 0.074115, 0.050193, 0.077382,
+        2, 38, 0.048859, 0.074947, 0.013362, 0.089180, 0.041598, 0.045021, 0.025537, 0.066803, 0.048722, 0.074655,
+        2, 37, 0.040158, 0.065781, 0.012126, 0.080282, 0.038175, 0.036686, 0.023178, 0.062884, 0.047088, 0.072630,
+        2, 36, 0.033881, 0.058774, 0.011001, 0.072895, 0.032542, 0.028434, 0.020461, 0.057424, 0.045225, 0.069728,
+        2, 35, 0.030294, 0.052831, 0.009800, 0.069422, 0.029587, 0.024311, 0.019232, 0.052294, 0.043254, 0.067311,
+        2, 34, 0.026957, 0.048824, 0.008847, 0.065224, 0.028054, 0.020655, 0.018095, 0.049876, 0.041553, 0.064112,
+        2, 33, 0.024349, 0.045159, 0.007976, 0.060371, 0.026226, 0.018652, 0.016776, 0.047385, 0.039704, 0.061695,
+        2, 32, 0.022078, 0.040951, 0.007202, 0.055330, 0.024365, 0.017145, 0.016065, 0.043944, 0.037719, 0.057699,
+        2, 31, 0.020733, 0.035223, 0.006791, 0.052327, 0.022850, 0.015790, 0.015233, 0.041124, 0.035964, 0.054810,
+        2, 30, 0.019626, 0.029984, 0.006021, 0.046551, 0.021086, 0.014673, 0.013133, 0.037757, 0.034007, 0.049923,
+        2, 29, 0.018765, 0.025923, 0.005677, 0.039731, 0.018291, 0.013707, 0.011973, 0.033543, 0.031847, 0.047048,
+        2, 28, 0.017539, 0.023491, 0.005192, 0.035180, 0.017033, 0.013349, 0.011092, 0.031296, 0.029970, 0.044240,
+        2, 27, 0.016270, 0.021488, 0.004753, 0.032258, 0.015628, 0.012909, 0.010419, 0.028179, 0.028202, 0.041756,
+        2, 26, 0.015525, 0.019557, 0.004390, 0.029942, 0.014652, 0.012207, 0.009339, 0.024975, 0.025745, 0.037679,
+        2, 25, 0.014638, 0.018036, 0.004146, 0.026314, 0.013797, 0.011314, 0.009099, 0.018864, 0.023517, 0.032832,
+        2, 24, 0.014075, 0.016575, 0.003788, 0.024444, 0.013045, 0.010780, 0.008541, 0.015587, 0.019710, 0.028013,
+        2, 23, 0.013597, 0.015638, 0.003430, 0.022970, 0.011632, 0.010471, 0.008031, 0.012675, 0.015296, 0.023004,
+        2, 22, 0.012968, 0.014715, 0.003089, 0.021096, 0.010990, 0.009929, 0.007642, 0.010846, 0.012825, 0.017253,
+        2, 21, 0.012088, 0.014175, 0.002884, 0.020046, 0.010148, 0.009032, 0.006813, 0.008261, 0.010449, 0.013500,
+        2, 20, 0.010976, 0.013381, 0.002693, 0.016732, 0.009381, 0.007742, 0.005400, 0.006437, 0.008100, 0.010841,
+        2, 19, 0.009566, 0.012631, 0.001836, 0.013686, 0.007125, 0.006782, 0.003923, 0.005431, 0.005589, 0.008613,
+        2, 18, 0.008982, 0.011349, 0.001458, 0.011744, 0.005708, 0.005742, 0.002724, 0.004884, 0.003618, 0.006764,
+        2, 17, 0.008273, 0.009439, 0.000845, 0.009291, 0.004250, 0.004857, 0.002327, 0.004469, 0.002673, 0.004847,
+        2, 16, 0.007679, 0.007704, 0.000545, 0.007737, 0.003394, 0.003988, 0.001534, 0.004045, 0.001742, 0.003834,
+        2, 15, 0.007236, 0.005265, 0.000365, 0.006442, 0.002565, 0.003089, 0.000675, 0.003023, 0.000959, 0.002808,
+        2, 14, 0.007090, 0.003787, 0.000261, 0.004990, 0.001802, 0.002400, 0.000397, 0.002249, 0.000608, 0.002457,
+        2, 13, 0.006877, 0.003029, 0.000203, 0.004076, 0.001404, 0.001835, 0.000270, 0.001814, 0.000324, 0.002012,
+        2, 12, 0.006575, 0.002311, 0.000000, 0.003502, 0.001249, 0.001458, 0.000135, 0.001436, 0.000000, 0.001850,
+        2, 11, 0.006314, 0.001836, 0.000000, 0.003051, 0.001114, 0.000597, 0.000000, 0.000841, 0.000000, 0.001350,
+        2, 10, 0.005971, 0.001434, 0.000000, 0.002570, 0.000945, 0.000230, 0.000000, 0.000540, 0.000000, 0.001215,
+        2, 9, 0.005627, 0.001172, 0.000000, 0.001809, 0.000783, 0.000019, 0.000000, 0.000405, 0.000000, 0.000675,
+        2, 8, 0.005144, 0.000940, 0.000000, 0.001276, 0.000668, 0.000038, 0.000000, 0.000000, 0.000000, 0.000648,
+        2, 7, 0.004686, 0.000622, 0.000000, 0.000890, 0.000581, 0.000009, 0.000000, 0.000000, 0.000000, 0.000230,
+        2, 6, 0.004247, 0.000428, 0.000000, 0.000541, 0.000473, 0.000019, 0.000000, 0.000000, 0.000000, 0.000135,
+        2, 5, 0.003857, 0.000269, 0.000000, 0.000320, 0.000419, 0.000000, 0.000000, 0.000000, 0.000041, 0.000068,
+        2, 4, 0.001459, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        2, 3, 0.000213, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        2, 2, 0.000011, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        2, 1, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 40, 0.076761, 0.102506, 0.016124, 0.103138, 0.053330, 0.075546, 0.034795, 0.075122, 0.048600, 0.059400,
+        1, 39, 0.059789, 0.086189, 0.013921, 0.100518, 0.046637, 0.058995, 0.029252, 0.073440, 0.047763, 0.057672,
+        1, 38, 0.048114, 0.073888, 0.012658, 0.087901, 0.040794, 0.044596, 0.025404, 0.065367, 0.046035, 0.056025,
+        1, 37, 0.039012, 0.064789, 0.011340, 0.078422, 0.037284, 0.036393, 0.022955, 0.061854, 0.044955, 0.054729,
+        1, 36, 0.032905, 0.057594, 0.010346, 0.070816, 0.031725, 0.027540, 0.020264, 0.056074, 0.043821, 0.052056,
+        1, 35, 0.029808, 0.051953, 0.008983, 0.068113, 0.028515, 0.023242, 0.019054, 0.051141, 0.041904, 0.050922,
+        1, 34, 0.026190, 0.047825, 0.008062, 0.063852, 0.026949, 0.019710, 0.017831, 0.048705, 0.040500, 0.049059,
+        1, 33, 0.023463, 0.044194, 0.007344, 0.058990, 0.025423, 0.017612, 0.016629, 0.046710, 0.038637, 0.046899,
+        1, 32, 0.021079, 0.039933, 0.006426, 0.053833, 0.023590, 0.016470, 0.015971, 0.043246, 0.036423, 0.044712,
+        1, 31, 0.020066, 0.034144, 0.006021, 0.051173, 0.022032, 0.014758, 0.015071, 0.040127, 0.034830, 0.043011,
+        1, 30, 0.018733, 0.028971, 0.005292, 0.044231, 0.020282, 0.013946, 0.012744, 0.037031, 0.032751, 0.039555,
+        1, 29, 0.018090, 0.024937, 0.005027, 0.037517, 0.017609, 0.013265, 0.011513, 0.032684, 0.030699, 0.036558,
+        1, 28, 0.016740, 0.022553, 0.004563, 0.033569, 0.016200, 0.012982, 0.010544, 0.030173, 0.028296, 0.034695,
+        1, 27, 0.015755, 0.020436, 0.004134, 0.030823, 0.014926, 0.012452, 0.010174, 0.026846, 0.026460, 0.032724,
+        1, 26, 0.014850, 0.018922, 0.003734, 0.028685, 0.013797, 0.011678, 0.009229, 0.024597, 0.024084, 0.029025,
+        1, 25, 0.013878, 0.017272, 0.003470, 0.025088, 0.013122, 0.010884, 0.009018, 0.018041, 0.021438, 0.024948,
+        1, 24, 0.013230, 0.015930, 0.003094, 0.023239, 0.012077, 0.010260, 0.008435, 0.014907, 0.017577, 0.022464,
+        1, 23, 0.012690, 0.014580, 0.002700, 0.021803, 0.010835, 0.009963, 0.007935, 0.011580, 0.013284, 0.018252,
+        1, 22, 0.011880, 0.014040, 0.002295, 0.020015, 0.010349, 0.009296, 0.007536, 0.009542, 0.010881, 0.013068,
+        1, 21, 0.011070, 0.013500, 0.002122, 0.018914, 0.008907, 0.008370, 0.006637, 0.006801, 0.008046, 0.010476,
+        1, 20, 0.009647, 0.012450, 0.002009, 0.015568, 0.007962, 0.007444, 0.005192, 0.004836, 0.005670, 0.008289,
+        1, 19, 0.008640, 0.011740, 0.001161, 0.012596, 0.006842, 0.006275, 0.002700, 0.003834, 0.003186, 0.005751,
+        1, 18, 0.008262, 0.010171, 0.000783, 0.010622, 0.004965, 0.005273, 0.002071, 0.003251, 0.001728, 0.005157,
+        1, 17, 0.007420, 0.008640, 0.000340, 0.008211, 0.003791, 0.004271, 0.001836, 0.002835, 0.000918, 0.002943,
+        1, 16, 0.007136, 0.007020, 0.000000, 0.006672, 0.003213, 0.003213, 0.001080, 0.002419, 0.000189, 0.001917,
+        1, 15, 0.006939, 0.004590, 0.000000, 0.005589, 0.002012, 0.002722, 0.000000, 0.001871, 0.000108, 0.001215,
+        1, 14, 0.006753, 0.003083, 0.000000, 0.003888, 0.001229, 0.001966, 0.000000, 0.001285, 0.000189, 0.001161,
+        1, 13, 0.006534, 0.002279, 0.000000, 0.003075, 0.000878, 0.001455, 0.000000, 0.001002, 0.000000, 0.000756,
+        1, 12, 0.006251, 0.001647, 0.000000, 0.002700, 0.000837, 0.001134, 0.000000, 0.000756, 0.000000, 0.000891,
+        1, 11, 0.006013, 0.001045, 0.000000, 0.002376, 0.000716, 0.000491, 0.000000, 0.000246, 0.000000, 0.000648,
+        1, 10, 0.005732, 0.000845, 0.000000, 0.001836, 0.000648, 0.000189, 0.000000, 0.000000, 0.000000, 0.000540,
+        1, 9, 0.005076, 0.000697, 0.000000, 0.001134, 0.000473, 0.000038, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 8, 0.004523, 0.000540, 0.000000, 0.000662, 0.000446, 0.000076, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 7, 0.003972, 0.000294, 0.000000, 0.000429, 0.000378, 0.000019, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 6, 0.003564, 0.000254, 0.000000, 0.000208, 0.000270, 0.000038, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 5, 0.003210, 0.000122, 0.000000, 0.000230, 0.000311, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 4, 0.000489, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 3, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 2, 0.000022, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+        1, 1, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
+    -1], "");
+
+    temperature_weights_database = VectorParam.Int([
+        71, 1,
+        72, 2,
+        73, 3,
+        74, 4,
+        75, 5,
+        76, 5,
+        77, 6,
+        78, 7,
+        79, 8,
+        80, 10,
+        81, 11,
+        82, 12,
+        83, 12,
+        84, 13,
+        85, 14,
+        86, 16,
+        87, 17,
+        88, 18,
+        89, 19,
+        90, 20,
+        91, 22,
+        92, 24,
+        93, 26,
+        94, 27,
+        95, 29,
+        96, 30,
+        97, 32,
+        98, 35,
+        99, 37,
+        100, 39,
+        101, 42,
+        102, 45,
+        103, 47,
+        104, 50,
+        105, 53,
+        106, 56,
+        107, 61,
+        108, 65,
+        109, 70,
+        110, 74,
+        111, 78,
+        112, 82,
+        113, 89,
+        114, 95,
+        115, 100,
+        116, 106,
+        117, 115,
+        118, 122,
+        119, 130,
+        120, 139,
+        121, 147,
+        122, 156,
+        123, 169,
+        124, 178,
+        125, 190,
+    -1], "");
diff --git a/src/mem/ruby/network/fault_model/SConscript b/src/mem/ruby/network/fault_model/SConscript
new file mode 100644 (file)
index 0000000..ade3eca
--- /dev/null
@@ -0,0 +1,43 @@
+# 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)
+
+Import('*')
+
+if env['PROTOCOL'] == 'None':
+    Return()
+
+SimObject('FaultModel.py')
+Source('FaultModel.cc')
+
index e3eb73b0a225e9ed24b168e3c09fd54e6fee4949..cd4ca0af14168599f5140303cafe6a8a35c78661 100644 (file)
@@ -38,6 +38,9 @@ BaseGarnetNetwork::BaseGarnetNetwork(const Params *p)
 {
     m_ni_flit_size = p->ni_flit_size;
     m_vcs_per_vnet = p->vcs_per_vnet;
+    m_enable_fault_model = p->enable_fault_model;
+    if (m_enable_fault_model)
+        fault_model = p->fault_model;
 
     m_ruby_start = 0;
     m_flits_received = 0;
index 95d4c5f5c5669a23dbb6bc1e3900288adb07d4ec..52079d8f67d53c6a5733850f8b5389ff126c5e58 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "mem/ruby/network/garnet/NetworkHeader.hh"
 #include "mem/ruby/network/Network.hh"
+#include "mem/ruby/network/fault_model/FaultModel.hh"
 #include "params/BaseGarnetNetwork.hh"
 #include "math.h"
 
@@ -50,10 +51,13 @@ class BaseGarnetNetwork : public Network
     void init();
     int getNiFlitSize() {return m_ni_flit_size; }
     int getVCsPerVnet() {return m_vcs_per_vnet; }
+    bool isFaultModelEnabled() {return m_enable_fault_model;}
+    FaultModel* fault_model;
 
   protected:
     int m_ni_flit_size;
     int m_vcs_per_vnet;
+    bool m_enable_fault_model;
 
     int m_flits_received;
     int m_flits_injected;
index 8073131f4221906a7ccb011fdb9d6443f1b6daea..2431db20364303cd7f1ffd28d352f7915be3838f 100644 (file)
@@ -36,3 +36,5 @@ class BaseGarnetNetwork(RubyNetwork):
     abstract = True
     ni_flit_size = Param.Int(16, "network interface flit size in bytes")
     vcs_per_vnet = Param.Int(4, "virtual channels per virtual network");
+    enable_fault_model = Param.Bool(False, "enable network fault model");
+    fault_model = Param.FaultModel(NULL, "network fault model");
index be9a92305d7d9048232ceabf2aa3c98f88412f45..fccd73ee2dca290155af9e6f35cd9d2afc1d2aee 100644 (file)
@@ -97,6 +97,23 @@ GarnetNetwork_d::init()
         NetworkLink_d* net_link = safe_cast<NetworkLink_d*>(*i);
         net_link->init_net_ptr(this);
     }
+
+    // FaultModel: declare each router to the fault model
+    if(isFaultModelEnabled()){
+        for (vector<Router_d*>::const_iterator i= m_router_ptr_vector.begin();
+             i != m_router_ptr_vector.end(); ++i) {
+            Router_d* router = safe_cast<Router_d*>(*i);
+            int router_id=fault_model->declare_router(router->get_num_inports(),
+                                                      router->get_num_outports(),
+                                                      router->get_vc_per_vnet(),
+                                                      getBuffersPerDataVC(),
+                                                      getBuffersPerCtrlVC());
+            assert(router_id == router->get_id());
+            router->printAggregateFaultProbability(cout);
+            router->printFaultVector(cout);
+        }
+    }
+
 }
 
 GarnetNetwork_d::~GarnetNetwork_d()
index 2030bb4f0be74a4670e1b4a1c164a3fc07ebf10f..a7fe05a64d7fc5916a37ae84834b8f95bbcb415b 100644 (file)
@@ -39,6 +39,7 @@
 #include "mem/ruby/network/Network.hh"
 #include "params/GarnetNetwork_d.hh"
 
+class FaultModel;
 class NetworkInterface_d;
 class MessageBuffer;
 class Router_d;
index 62ab5ce07f881ecbdf2e9efbb09ae75f7a33a25e..b638c9aca0ebd58bc1b29ba8db5540b4d6ac11bf 100644 (file)
@@ -189,6 +189,35 @@ Router_d::printConfig(ostream& out)
     out << "]" << endl;
 }
 
+void
+Router_d::printFaultVector(ostream& out)
+{
+    int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
+    int num_fault_types = m_network_ptr->fault_model->number_of_fault_types;
+    float fault_vector[num_fault_types];
+    get_fault_vector(temperature_celcius, fault_vector);
+    out << "Router-" << m_id << " fault vector: " << endl;
+    for (int fault_type_index = 0; fault_type_index < num_fault_types;
+         fault_type_index++){
+        out << " - probability of (";
+        out << 
+        m_network_ptr->fault_model->fault_type_to_string(fault_type_index);
+        out << ") = ";
+        out << fault_vector[fault_type_index] << endl;
+    }
+}
+
+void
+Router_d::printAggregateFaultProbability(std::ostream& out)
+{
+    int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
+    float aggregate_fault_prob;
+    get_aggregate_fault_probability(temperature_celcius, 
+                                    &aggregate_fault_prob);
+    out << "Router-" << m_id << " fault probability: ";
+    out << aggregate_fault_prob << endl;
+}
+
 Router_d *
 GarnetRouter_dParams::create()
 {
index e5a3a0ce272d5066f3ecd5c66b94128f65773d6c..babc0d443d56f1816f36ee4639069cd64b8bec41 100644 (file)
@@ -50,6 +50,7 @@ class RoutingUnit_d;
 class VCallocator_d;
 class SWallocator_d;
 class Switch_d;
+class FaultModel;
 
 class Router_d : public BasicRouter
 {
@@ -86,6 +87,8 @@ class Router_d : public BasicRouter
     void vcarb_req();
     void swarb_req();
     void printConfig(std::ostream& out);
+    void printFaultVector(std::ostream& out);
+    void printAggregateFaultProbability(std::ostream& out);
 
     double calculate_power();
     void calculate_performance_numbers();
@@ -93,6 +96,15 @@ class Router_d : public BasicRouter
     double get_dynamic_power(){return m_power_dyn;}
     double get_static_power(){return m_power_sta;}
     double get_clk_power(){return m_clk_power;}
+    bool get_fault_vector(int temperature, float fault_vector[]){ 
+        return m_network_ptr->fault_model->fault_vector(m_id, temperature, 
+                                                        fault_vector); 
+    }
+    bool get_aggregate_fault_probability(int temperature, 
+                                         float *aggregate_fault_prob){
+        return m_network_ptr->fault_model->fault_prob(m_id, temperature, 
+                                                      aggregate_fault_prob);
+    }
 
   private:
     int m_virtual_networks, m_num_vcs, m_vc_per_vnet;