| /***************************************************************************** |
| * McPAT |
| * SOFTWARE LICENSE AGREEMENT |
| * Copyright 2012 Hewlett-Packard Development Company, L.P. |
| * Copyright (c) 2010-2013 Advanced Micro Devices, Inc. |
| * 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 <cassert> |
| #include <iostream> |
| |
| #include "basic_components.h" |
| #include "interconnect.h" |
| #include "wire.h" |
| |
| double Interconnect::width_scaling_threshold = 3.0; |
| |
| Interconnect::Interconnect(XMLNode* _xml_data, string name_, |
| enum Device_ty device_ty_, double base_w, |
| double base_h, int data_w, |
| double len, |
| const InputParameter *configure_interface, |
| int start_wiring_level_, double _clockRate, |
| bool pipelinable_, double route_over_perc_, |
| bool opt_local_, enum Core_type core_ty_, |
| enum Wire_type wire_model, |
| double width_s, double space_s, |
| TechnologyParameter::DeviceType *dt) |
| : McPATComponent(_xml_data), device_ty(device_ty_), in_rise_time(0), |
| out_rise_time(0), base_width(base_w), base_height(base_h), |
| data_width(data_w), wt(wire_model), width_scaling(width_s), |
| space_scaling(space_s), start_wiring_level(start_wiring_level_), |
| length(len), opt_local(opt_local_), core_ty(core_ty_), |
| pipelinable(pipelinable_), route_over_perc(route_over_perc_), |
| deviceType(dt) { |
| name = name_; |
| clockRate = _clockRate; |
| l_ip = *configure_interface; |
| local_result = init_interface(&l_ip, name); |
| |
| max_unpipelined_link_delay = 0; |
| min_w_nmos = g_tp.min_w_nmos_; |
| min_w_pmos = deviceType->n_to_p_eff_curr_drv_ratio * min_w_nmos; |
| |
| |
| |
| latency = l_ip.latency; |
| throughput = l_ip.throughput; |
| latency_overflow = false; |
| throughput_overflow = false; |
| |
| if (pipelinable == false) { |
| //Non-pipelinable wires, such as bypass logic, care latency |
| calcWireData(); |
| if (opt_for_clk && opt_local) { |
| while (delay > latency && |
| width_scaling < width_scaling_threshold) { |
| width_scaling *= 2; |
| space_scaling *= 2; |
| Wire winit(width_scaling, space_scaling); |
| calcWireData(); |
| } |
| if (delay > latency) { |
| latency_overflow = true; |
| } |
| } |
| } else { |
| //Pipelinable wires, such as bus, does not care latency but throughput |
| calcWireData(); |
| if (opt_for_clk && opt_local) { |
| while (delay > throughput && |
| width_scaling < width_scaling_threshold) { |
| width_scaling *= 2; |
| space_scaling *= 2; |
| Wire winit(width_scaling, space_scaling); |
| calcWireData(); |
| } |
| if (delay > throughput) { |
| // insert pipeline stages |
| num_pipe_stages = (int)ceil(delay / throughput); |
| assert(num_pipe_stages > 0); |
| delay = delay / num_pipe_stages + num_pipe_stages * 0.05 * delay; |
| } |
| } |
| } |
| |
| power_bit = power; |
| power.readOp.dynamic *= data_width; |
| power.readOp.leakage *= data_width; |
| power.readOp.gate_leakage *= data_width; |
| area.set_area(area.get_area()*data_width); |
| no_device_under_wire_area.h *= data_width; |
| |
| if (latency_overflow == true) { |
| cout << "Warning: " << name |
| << " wire structure cannot satisfy latency constraint." << endl; |
| } |
| |
| assert(power.readOp.dynamic > 0); |
| assert(power.readOp.leakage > 0); |
| assert(power.readOp.gate_leakage > 0); |
| |
| double long_channel_device_reduction = |
| longer_channel_device_reduction(device_ty, core_ty); |
| |
| double sckRation = g_tp.sckt_co_eff; |
| power.readOp.dynamic *= sckRation; |
| power.writeOp.dynamic *= sckRation; |
| power.searchOp.dynamic *= sckRation; |
| |
| power.readOp.longer_channel_leakage = |
| power.readOp.leakage * long_channel_device_reduction; |
| |
| //Only global wires has the option to choose whether routing over or not |
| if (pipelinable) |
| area.set_area(area.get_area() * route_over_perc + |
| no_device_under_wire_area.get_area() * |
| (1 - route_over_perc)); |
| |
| Wire wreset(); |
| } |
| |
| |
| |
| void |
| Interconnect::calcWireData() { |
| |
| Wire *wtemp1 = 0; |
| wtemp1 = new Wire(wt, length, 1, width_scaling, space_scaling); |
| delay = wtemp1->delay; |
| power.readOp.dynamic = wtemp1->power.readOp.dynamic; |
| power.readOp.leakage = wtemp1->power.readOp.leakage; |
| power.readOp.gate_leakage = wtemp1->power.readOp.gate_leakage; |
| |
| area.set_area(wtemp1->area.get_area()); |
| no_device_under_wire_area.h = (wtemp1->wire_width + wtemp1->wire_spacing); |
| no_device_under_wire_area.w = length; |
| |
| if (wtemp1) |
| delete wtemp1; |
| |
| } |
| |
| void |
| Interconnect::computeEnergy() { |
| double pppm_t[4] = {1, 1, 1, 1}; |
| |
| // Compute TDP |
| power_t.reset(); |
| set_pppm(pppm_t, int_params.active_ports * int_stats.duty_cycle, |
| int_params.active_ports, int_params.active_ports, |
| int_params.active_ports * int_stats.duty_cycle); |
| power_t = power * pppm_t; |
| |
| rt_power.reset(); |
| set_pppm(pppm_t, int_stats.accesses, int_params.active_ports, |
| int_params.active_ports, int_stats.accesses); |
| rt_power = power * pppm_t; |
| |
| output_data.peak_dynamic_power = power_t.readOp.dynamic * clockRate; |
| output_data.subthreshold_leakage_power = power_t.readOp.leakage; |
| output_data.gate_leakage_power = power_t.readOp.gate_leakage; |
| output_data.runtime_dynamic_energy = rt_power.readOp.dynamic; |
| } |
| |
| void |
| Interconnect::computeArea() { |
| output_data.area = area.get_area() / 1e6; |
| } |
| |
| void |
| Interconnect::set_params_stats(double active_ports, |
| double duty_cycle, double accesses) { |
| int_params.active_ports = active_ports; |
| int_stats.duty_cycle = duty_cycle; |
| int_stats.accesses = accesses; |
| } |
| |
| void Interconnect::leakage_feedback(double temperature) { |
| l_ip.temp = (unsigned int)round(temperature/10.0)*10; |
| uca_org_t init_result = init_interface(&l_ip, name); // init_result is dummy |
| |
| calcWireData(); |
| |
| power_bit = power; |
| power.readOp.dynamic *= data_width; |
| power.readOp.leakage *= data_width; |
| power.readOp.gate_leakage *= data_width; |
| |
| assert(power.readOp.dynamic > 0); |
| assert(power.readOp.leakage > 0); |
| assert(power.readOp.gate_leakage > 0); |
| |
| double long_channel_device_reduction = |
| longer_channel_device_reduction(device_ty,core_ty); |
| |
| double sckRation = g_tp.sckt_co_eff; |
| power.readOp.dynamic *= sckRation; |
| power.writeOp.dynamic *= sckRation; |
| power.searchOp.dynamic *= sckRation; |
| |
| power.readOp.longer_channel_leakage = |
| power.readOp.leakage*long_channel_device_reduction; |
| } |
| |