summaryrefslogtreecommitdiff
path: root/src/mem/ruby/network/orion/power_crossbar.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/ruby/network/orion/power_crossbar.cc')
-rw-r--r--src/mem/ruby/network/orion/power_crossbar.cc365
1 files changed, 365 insertions, 0 deletions
diff --git a/src/mem/ruby/network/orion/power_crossbar.cc b/src/mem/ruby/network/orion/power_crossbar.cc
new file mode 100644
index 000000000..d3e2232ae
--- /dev/null
+++ b/src/mem/ruby/network/orion/power_crossbar.cc
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * 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.
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#include "power_ll.hh"
+#include "power_crossbar.hh"
+#include "parm_technology.hh"
+#include "SIM_port.hh"
+#include "power_static.hh"
+#include "power_utils.hh"
+
+/*-------------------- CROSSBAR power model -------------------*/
+
+static double crossbar_in_cap(double wire_cap, unsigned n_out, int connect_type, int trans_type, double *Nsize)
+{
+ double Ctotal = 0, Ctrans = 0, psize, nsize, Cdriver = 0;
+
+ /* part 1: wire cap */
+ Ctotal += wire_cap;
+ //printf("CROSSBAR_INTERNAL: input wire cap = %g\n", wire_cap);
+
+ /* part 2: drain cap of transmission gate or gate cap of tri-state gate */
+ if (connect_type == TRANS_GATE) {
+ /* FIXME: resizing strategy */
+ nsize = Nsize ? *Nsize : Wmemcellr;
+ psize = nsize * Wdecinvp / Wdecinvn;
+ Ctrans = SIM_power_draincap(nsize, NCH, 1);
+ if (trans_type == NP_GATE)
+ Ctrans += SIM_power_draincap(psize, PCH, 1);
+ }
+ else if (connect_type == TRISTATE_GATE) {
+ Ctrans = SIM_power_gatecap(Woutdrvnandn + Woutdrvnandp, 0) +
+ SIM_power_gatecap(Woutdrvnorn + Woutdrvnorp, 0);
+ }
+ else {/* some error handler */}
+
+ //printf("CROSSBAR_INTERNAL: input connector cap = %g\n", (n_out * Ctrans));
+ Ctotal += n_out * Ctrans;
+
+ /* part 3: input driver */
+ /* FIXME: how to specify timing? */
+ psize = SIM_power_driver_size(Ctotal, Period / 3);
+ nsize = psize * Wdecinvn / Wdecinvp;
+ Cdriver = SIM_power_draincap(nsize, NCH, 1) + SIM_power_draincap(psize, PCH, 1) +
+ SIM_power_gatecap(nsize + psize, 0);
+
+ //printf("CROSSBAR_INTERNAL: input driver cap = %g\n", Cdriver);
+
+ Ctotal += Cdriver;
+
+ return Ctotal / 2;
+}
+
+
+static double crossbar_out_cap(double length, unsigned n_in, int connect_type, int trans_type, double *Nsize)
+{
+ double Ctotal = 0, Cwire = 0, Ctrans = 0, Cdriver = 0, psize, nsize;
+
+ /* part 1: wire cap */
+ Cwire += CC3metal * length;
+ //printf("CROSSBAR_INTERNAL: output wire cap = %g\n", Cwire);
+
+ Ctotal += Cwire;
+
+ /* part 2: drain cap of transmission gate or tri-state gate */
+ if (connect_type == TRANS_GATE) {
+ /* FIXME: resizing strategy */
+ if (Nsize) {
+ /* FIXME: how to specify timing? */
+ psize = SIM_power_driver_size(Ctotal, Period / 3);
+ *Nsize = nsize = psize * Wdecinvn / Wdecinvp;
+ }
+ else {
+ nsize = Wmemcellr;
+ psize = nsize * Wdecinvp / Wdecinvn;
+ }
+ Ctrans = SIM_power_draincap(nsize, NCH, 1);
+ if (trans_type == NP_GATE)
+ Ctrans += SIM_power_draincap(psize, PCH, 1);
+ }
+ else if (connect_type == TRISTATE_GATE) {
+ Ctrans = SIM_power_draincap(Woutdrivern, NCH, 1) + SIM_power_draincap(Woutdriverp, PCH, 1);
+ }
+ else {/* some error handler */}
+
+ //printf("CROSSBAR_INTERNAL: output connector cap = %g\n", (n_in * Ctrans));
+ Ctotal += n_in * Ctrans;
+
+ /* part 3: output driver */
+ Cdriver += SIM_power_draincap(Woutdrivern, NCH, 1) + SIM_power_draincap(Woutdriverp, PCH, 1) +
+ SIM_power_gatecap(Woutdrivern + Woutdriverp, 0);
+
+ //printf("CROSSBAR_INTERNAL: output driver cap = %g\n", Cdriver);
+
+ Ctotal += Cdriver;
+
+ return Ctotal / 2;
+}
+
+
+/* cut-through crossbar only supports 4x4 now */
+static double crossbar_io_cap(double length)
+{
+ double Ctotal = 0, psize, nsize;
+
+ /* part 1: wire cap */
+ Ctotal += CC3metal * length;
+
+ /* part 2: gate cap of tri-state gate */
+ Ctotal += 2 * (SIM_power_gatecap(Woutdrvnandn + Woutdrvnandp, 0) +
+ SIM_power_gatecap(Woutdrvnorn + Woutdrvnorp, 0));
+
+ /* part 3: drain cap of tri-state gate */
+ Ctotal += 2 * (SIM_power_draincap(Woutdrivern, NCH, 1) + SIM_power_draincap(Woutdriverp, PCH, 1));
+
+ /* part 4: input driver */
+ /* FIXME: how to specify timing? */
+ psize = SIM_power_driver_size(Ctotal, Period * 0.8);
+ nsize = psize * Wdecinvn / Wdecinvp;
+ Ctotal += SIM_power_draincap(nsize, NCH, 1) + SIM_power_draincap(psize, PCH, 1) +
+ SIM_power_gatecap(nsize + psize, 0);
+
+ /* part 5: output driver */
+ Ctotal += SIM_power_draincap(Woutdrivern, NCH, 1) + SIM_power_draincap(Woutdriverp, PCH, 1) +
+ SIM_power_gatecap(Woutdrivern + Woutdriverp, 0);
+
+ /* HACK HACK HACK */
+ /* this HACK is to count a 1:4 mux and a 4:1 mux, so we have a 5x5 crossbar */
+ return Ctotal / 2 * 1.32;
+}
+
+
+static double crossbar_int_cap(unsigned degree, int connect_type, int trans_type)
+{
+ double Ctotal = 0, Ctrans;
+
+ if (connect_type == TRANS_GATE) {
+ /* part 1: drain cap of transmission gate */
+ /* FIXME: Wmemcellr and resize */
+ Ctrans = SIM_power_draincap(Wmemcellr, NCH, 1);
+ if (trans_type == NP_GATE)
+ Ctrans += SIM_power_draincap(Wmemcellr * Wdecinvp / Wdecinvn, PCH, 1);
+ Ctotal += (degree + 1) * Ctrans;
+ }
+ else if (connect_type == TRISTATE_GATE) {
+ /* part 1: drain cap of tri-state gate */
+ Ctotal += degree * (SIM_power_draincap(Woutdrivern, NCH, 1) + SIM_power_draincap(Woutdriverp, PCH, 1));
+
+ /* part 2: gate cap of tri-state gate */
+ Ctotal += SIM_power_gatecap(Woutdrvnandn + Woutdrvnandp, 0) +
+ SIM_power_gatecap(Woutdrvnorn + Woutdrvnorp, 0);
+ }
+ else {/* some error handler */}
+
+ return Ctotal / 2;
+}
+
+
+/* FIXME: segment control signals are not handled yet */
+static double crossbar_ctr_cap(double length, unsigned data_width, int prev_ctr, int next_ctr, unsigned degree, int connect_type, int trans_type)
+{
+ double Ctotal = 0, Cgate;
+
+ /* part 1: wire cap */
+ Ctotal = Cmetal * length;
+
+ /* part 2: gate cap of transmission gate or tri-state gate */
+ if (connect_type == TRANS_GATE) {
+ /* FIXME: Wmemcellr and resize */
+ Cgate = SIM_power_gatecap(Wmemcellr, 0);
+ if (trans_type == NP_GATE)
+ Cgate += SIM_power_gatecap(Wmemcellr * Wdecinvp / Wdecinvn, 0);
+ }
+ else if (connect_type == TRISTATE_GATE) {
+ Cgate = SIM_power_gatecap(Woutdrvnandn + Woutdrvnandp, 0) +
+ SIM_power_gatecap(Woutdrvnorn + Woutdrvnorp, 0);
+ }
+ else {/* some error handler */}
+
+ Ctotal += data_width * Cgate;
+
+ /* part 3: inverter */
+ if (!(connect_type == TRANS_GATE && trans_type == N_GATE && !prev_ctr))
+ /* FIXME: need accurate size, use minimal size for now */
+ Ctotal += SIM_power_draincap(Wdecinvn, NCH, 1) + SIM_power_draincap(Wdecinvp, PCH, 1) +
+ SIM_power_gatecap(Wdecinvn + Wdecinvp, 0);
+
+ /* part 4: drain cap of previous level control signal */
+ if (prev_ctr)
+ /* FIXME: need actual size, use decoder data for now */
+ Ctotal += degree * SIM_power_draincap(WdecNORn, NCH, 1) + SIM_power_draincap(WdecNORp, PCH, degree);
+
+ /* part 5: gate cap of next level control signal */
+ if (next_ctr)
+ /* FIXME: need actual size, use decoder data for now */
+ Ctotal += SIM_power_gatecap(WdecNORn + WdecNORp, degree * 40 + 20);
+
+ return Ctotal;
+}
+
+
+int power_crossbar_init(power_crossbar *crsbar, int model, unsigned n_in, unsigned n_out, unsigned data_width, unsigned degree, int connect_type, int trans_type, double in_len, double out_len, double *req_len)
+{
+ double in_length, out_length, ctr_length, Nsize, in_wire_cap, i_leakage;
+
+ if ((crsbar->model = model) && model < CROSSBAR_MAX_MODEL) {
+ crsbar->n_in = n_in;
+ crsbar->n_out = n_out;
+ crsbar->data_width = data_width;
+ crsbar->degree = degree;
+ crsbar->connect_type = connect_type;
+ crsbar->trans_type = trans_type;
+ /* redundant field */
+ crsbar->mask = HAMM_MASK(data_width);
+
+ crsbar->n_chg_in = crsbar->n_chg_int = crsbar->n_chg_out = crsbar->n_chg_ctr = 0;
+
+ switch (model) {
+ case MATRIX_CROSSBAR:
+
+ /* FIXME: need accurate spacing */
+ in_length = n_out * data_width * CrsbarCellWidth;
+ out_length = n_in * data_width * CrsbarCellHeight;
+ if (in_length < in_len) in_length = in_len;
+ if (out_length < out_len) out_length = out_len;
+ ctr_length = in_length / 2;
+ if (req_len) *req_len = in_length;
+
+ in_wire_cap = in_length * CC3metal;
+
+ crsbar->e_chg_out = crossbar_out_cap(out_length, n_in, connect_type, trans_type, &Nsize) * EnergyFactor;
+ crsbar->e_chg_in = crossbar_in_cap(in_wire_cap, n_out, connect_type, trans_type, &Nsize) * EnergyFactor;
+ /* FIXME: wire length estimation, really reset? */
+ /* control signal should reset after transmission is done, so no 1/2 */
+ crsbar->e_chg_ctr = crossbar_ctr_cap(ctr_length, data_width, 0, 0, 0, connect_type, trans_type) * EnergyFactor;
+ crsbar->e_chg_int = 0;
+
+ /* static power */
+ i_leakage = 0;
+ /* tri-state buffers */
+ i_leakage += ((Woutdrvnandp * (NAND2_TAB[0] + NAND2_TAB[1] + NAND2_TAB[2]) + Woutdrvnandn * NAND2_TAB[3]) / 4 +
+ (Woutdrvnorp * NOR2_TAB[0] + Woutdrvnorn * (NOR2_TAB[1] + NOR2_TAB[2] + NOR2_TAB[3])) / 4 +
+ Woutdrivern * NMOS_TAB[0] + Woutdriverp * PMOS_TAB[0]) * n_in * n_out * data_width;
+ /* input driver */
+ i_leakage += (Wdecinvn * NMOS_TAB[0] + Wdecinvp * PMOS_TAB[0]) * n_in * data_width;
+ /* output driver */
+ i_leakage += (Woutdrivern * NMOS_TAB[0] + Woutdriverp * PMOS_TAB[0]) * n_out * data_width;
+ /* control signal inverter */
+ i_leakage += (Wdecinvn * NMOS_TAB[0] + Wdecinvp * PMOS_TAB[0]) * n_in * n_out;
+ crsbar->i_leakage = i_leakage / PARM_TECH_POINT * 100;
+ break;
+
+ case MULTREE_CROSSBAR:
+ /* input wire horizontal segment length */
+ in_length = n_in * data_width * CrsbarCellWidth * (n_out / 2);
+ in_wire_cap = in_length * CCmetal;
+ /* input wire vertical segment length */
+ in_length = n_in * data_width * (5 * Lamda) * (n_out / 2);
+ in_wire_cap += in_length * CC3metal;
+
+ ctr_length = n_in * data_width * CrsbarCellWidth * (n_out / 2) / 2;
+
+ crsbar->e_chg_out = crossbar_out_cap(0, degree, connect_type, trans_type, NULL) * EnergyFactor;
+ crsbar->e_chg_in = crossbar_in_cap(in_wire_cap, n_out, connect_type, trans_type, NULL) * EnergyFactor;
+ crsbar->e_chg_int = crossbar_int_cap(degree, connect_type, trans_type) * EnergyFactor;
+
+ /* redundant field */
+ crsbar->depth = (unsigned)ceil(log(n_in) / log(degree));
+
+ /* control signal should reset after transmission is done, so no 1/2 */
+ if (crsbar->depth == 1)
+ /* only one level of control signal */
+ crsbar->e_chg_ctr = crossbar_ctr_cap(ctr_length, data_width, 0, 0, degree, connect_type, trans_type) * EnergyFactor;
+ else {
+ /* first level and last level control signals */
+ crsbar->e_chg_ctr = crossbar_ctr_cap(ctr_length, data_width, 0, 1, degree, connect_type, trans_type) * EnergyFactor +
+ crossbar_ctr_cap(0, data_width, 1, 0, degree, connect_type, trans_type) * EnergyFactor;
+ /* intermediate control signals */
+ if (crsbar->depth > 2)
+ crsbar->e_chg_ctr += (crsbar->depth - 2) * crossbar_ctr_cap(0, data_width, 1, 1, degree, connect_type, trans_type) * EnergyFactor;
+ }
+
+ /* static power */
+ i_leakage = 0;
+ /* input driver */
+ i_leakage += (Wdecinvn * NMOS_TAB[0] + Wdecinvp * PMOS_TAB[0]) * n_in * data_width;
+ /* output driver */
+ i_leakage += (Woutdrivern * NMOS_TAB[0] + Woutdriverp * PMOS_TAB[0]) * n_out * data_width;
+ /* mux */
+ i_leakage += (WdecNORp * NOR2_TAB[0] + WdecNORn * (NOR2_TAB[1] + NOR2_TAB[2] + NOR2_TAB[3])) / 4 * (2 * n_in - 1) * n_out * data_width;
+ /* control signal inverter */
+ i_leakage += (Wdecinvn * NMOS_TAB[0] + Wdecinvp * PMOS_TAB[0]) * n_in * n_out;
+ crsbar->i_leakage = i_leakage / PARM_TECH_POINT * 100;
+ break;
+
+ default: break;/* some error handler */
+ }
+
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+/* FIXME: MULTREE_CROSSBAR record missing */
+int crossbar_record(power_crossbar *xb, int io, unsigned long int new_data, unsigned long int old_data, unsigned new_port, unsigned old_port)
+{
+ switch (xb->model) {
+ case MATRIX_CROSSBAR:
+ if (io) /* input port */
+ xb->n_chg_in += SIM_power_Hamming(new_data, old_data, xb->mask);
+ else { /* output port */
+ xb->n_chg_out += SIM_power_Hamming(new_data, old_data, xb->mask);
+ xb->n_chg_ctr += new_port != old_port;
+ }
+ break;
+
+ case MULTREE_CROSSBAR:
+ break;
+
+ default: break;/* some error handler */
+ }
+
+ return 0;
+}
+
+
+double crossbar_report(power_crossbar *crsbar)
+{
+ return (crsbar->n_chg_in * crsbar->e_chg_in + crsbar->n_chg_out * crsbar->e_chg_out +
+ crsbar->n_chg_int * crsbar->e_chg_int + crsbar->n_chg_ctr * crsbar->e_chg_ctr);
+}
+
+/* ---------- crossbar model ---------- */
+
+
+