1/*****************************************************************************
2 *                                McPAT
3 *                      SOFTWARE LICENSE AGREEMENT
4 *            Copyright 2012 Hewlett-Packard Development Company, L.P.
5 *            Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
6 *                          All Rights Reserved
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer;
12 * redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution;
15 * neither the name of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 ***************************************************************************/
32
33
34#include <cassert>
35#include <iostream>
36
37#include "basic_components.h"
38#include "interconnect.h"
39#include "wire.h"
40
41double Interconnect::width_scaling_threshold = 3.0;
42
43Interconnect::Interconnect(XMLNode* _xml_data, string name_,
44                           enum Device_ty device_ty_, double base_w,
45                           double base_h, int data_w,
46                           double len,
47                           const InputParameter *configure_interface,
48                           int start_wiring_level_, double _clockRate,
49                           bool pipelinable_, double route_over_perc_,
50                           bool opt_local_, enum Core_type core_ty_,
51                           enum Wire_type wire_model,
52                           double width_s, double space_s,
53                           TechnologyParameter::DeviceType *dt)
54    : McPATComponent(_xml_data), device_ty(device_ty_), in_rise_time(0),
55      out_rise_time(0), base_width(base_w), base_height(base_h),
56      data_width(data_w), wt(wire_model), width_scaling(width_s),
57      space_scaling(space_s), start_wiring_level(start_wiring_level_),
58      length(len), opt_local(opt_local_), core_ty(core_ty_),
59      pipelinable(pipelinable_), route_over_perc(route_over_perc_),
60      deviceType(dt) {
61    name = name_;
62    clockRate = _clockRate;
63    l_ip = *configure_interface;
64    local_result = init_interface(&l_ip, name);
65
66    max_unpipelined_link_delay = 0;
67    min_w_nmos = g_tp.min_w_nmos_;
68    min_w_pmos = deviceType->n_to_p_eff_curr_drv_ratio * min_w_nmos;
69
70
71
72    latency               = l_ip.latency;
73    throughput            = l_ip.throughput;
74    latency_overflow = false;
75    throughput_overflow = false;
76
77    if (pipelinable == false) {
78        //Non-pipelinable wires, such as bypass logic, care latency
79        calcWireData();
80        if (opt_for_clk && opt_local) {
81            while (delay > latency &&
82                   width_scaling < width_scaling_threshold) {
83                width_scaling *= 2;
84                space_scaling *= 2;
85                Wire winit(width_scaling, space_scaling);
86                calcWireData();
87            }
88            if (delay > latency) {
89                latency_overflow = true;
90            }
91        }
92    } else {
93        //Pipelinable wires, such as bus, does not care latency but throughput
94        calcWireData();
95        if (opt_for_clk && opt_local) {
96            while (delay > throughput &&
97                   width_scaling < width_scaling_threshold) {
98                width_scaling *= 2;
99                space_scaling *= 2;
100                Wire winit(width_scaling, space_scaling);
101                calcWireData();
102            }
103            if (delay > throughput) {
104                // insert pipeline stages
105                num_pipe_stages = (int)ceil(delay / throughput);
106                assert(num_pipe_stages > 0);
107                delay = delay / num_pipe_stages + num_pipe_stages * 0.05 * delay;
108            }
109        }
110    }
111
112    power_bit = power;
113    power.readOp.dynamic *= data_width;
114    power.readOp.leakage *= data_width;
115    power.readOp.gate_leakage *= data_width;
116    area.set_area(area.get_area()*data_width);
117    no_device_under_wire_area.h *= data_width;
118
119    if (latency_overflow == true) {
120        cout << "Warning: " << name
121             << " wire structure cannot satisfy latency constraint." << endl;
122    }
123
124    assert(power.readOp.dynamic > 0);
125    assert(power.readOp.leakage > 0);
126    assert(power.readOp.gate_leakage > 0);
127
128    double long_channel_device_reduction =
129        longer_channel_device_reduction(device_ty, core_ty);
130
131    double sckRation = g_tp.sckt_co_eff;
132    power.readOp.dynamic *= sckRation;
133    power.writeOp.dynamic *= sckRation;
134    power.searchOp.dynamic *= sckRation;
135
136    power.readOp.longer_channel_leakage =
137        power.readOp.leakage * long_channel_device_reduction;
138
139    //Only global wires has the option to choose whether routing over or not
140    if (pipelinable)
141        area.set_area(area.get_area() * route_over_perc +
142                      no_device_under_wire_area.get_area() *
143                      (1 - route_over_perc));
144
145    Wire wreset();
146}
147
148
149
150void
151Interconnect::calcWireData() {
152
153    Wire *wtemp1 = 0;
154    wtemp1 = new Wire(wt, length, 1, width_scaling, space_scaling);
155    delay = wtemp1->delay;
156    power.readOp.dynamic = wtemp1->power.readOp.dynamic;
157    power.readOp.leakage = wtemp1->power.readOp.leakage;
158    power.readOp.gate_leakage = wtemp1->power.readOp.gate_leakage;
159
160    area.set_area(wtemp1->area.get_area());
161    no_device_under_wire_area.h = (wtemp1->wire_width + wtemp1->wire_spacing);
162    no_device_under_wire_area.w = length;
163
164    if (wtemp1)
165        delete wtemp1;
166
167}
168
169void
170Interconnect::computeEnergy() {
171    double pppm_t[4] = {1, 1, 1, 1};
172
173    // Compute TDP
174    power_t.reset();
175    set_pppm(pppm_t, int_params.active_ports * int_stats.duty_cycle,
176            int_params.active_ports, int_params.active_ports,
177            int_params.active_ports * int_stats.duty_cycle);
178    power_t = power * pppm_t;
179
180    rt_power.reset();
181    set_pppm(pppm_t, int_stats.accesses, int_params.active_ports,
182             int_params.active_ports, int_stats.accesses);
183    rt_power = power * pppm_t;
184
185    output_data.peak_dynamic_power = power_t.readOp.dynamic * clockRate;
186    output_data.subthreshold_leakage_power = power_t.readOp.leakage;
187    output_data.gate_leakage_power = power_t.readOp.gate_leakage;
188    output_data.runtime_dynamic_energy = rt_power.readOp.dynamic;
189}
190
191void
192Interconnect::computeArea() {
193    output_data.area = area.get_area() / 1e6;
194}
195
196void
197Interconnect::set_params_stats(double active_ports,
198                               double duty_cycle, double accesses) {
199    int_params.active_ports = active_ports;
200    int_stats.duty_cycle = duty_cycle;
201    int_stats.accesses = accesses;
202}
203
204void Interconnect::leakage_feedback(double temperature) {
205  l_ip.temp = (unsigned int)round(temperature/10.0)*10;
206  uca_org_t init_result = init_interface(&l_ip, name); // init_result is dummy
207
208  calcWireData();
209
210  power_bit = power;
211  power.readOp.dynamic *= data_width;
212  power.readOp.leakage *= data_width;
213  power.readOp.gate_leakage *= data_width;
214
215  assert(power.readOp.dynamic > 0);
216  assert(power.readOp.leakage > 0);
217  assert(power.readOp.gate_leakage > 0);
218
219  double long_channel_device_reduction =
220      longer_channel_device_reduction(device_ty,core_ty);
221
222  double sckRation = g_tp.sckt_co_eff;
223  power.readOp.dynamic *= sckRation;
224  power.writeOp.dynamic *= sckRation;
225  power.searchOp.dynamic *= sckRation;
226
227  power.readOp.longer_channel_leakage =
228      power.readOp.leakage*long_channel_device_reduction;
229}
230
231