2014-04-01 18:44:30 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* McPAT
|
|
|
|
* SOFTWARE LICENSE AGREEMENT
|
|
|
|
* Copyright 2012 Hewlett-Packard Development Company, L.P.
|
2014-06-03 22:32:59 +02:00
|
|
|
* Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
|
2014-04-01 18:44:30 +02:00
|
|
|
* 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
|
2014-06-03 22:32:59 +02:00
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2014-04-01 18:44:30 +02:00
|
|
|
*
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
#include "basic_components.h"
|
2014-04-01 18:44:30 +02:00
|
|
|
#include "interconnect.h"
|
|
|
|
#include "wire.h"
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
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();
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
void
|
|
|
|
Interconnect::calcWireData() {
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
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;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
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;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
if (wtemp1)
|
|
|
|
delete wtemp1;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-06-03 22:32:59 +02:00
|
|
|
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;
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
void
|
|
|
|
Interconnect::computeArea() {
|
|
|
|
output_data.area = area.get_area() / 1e6;
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
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;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
void Interconnect::leakage_feedback(double temperature) {
|
2014-04-01 18:44:30 +02:00
|
|
|
l_ip.temp = (unsigned int)round(temperature/10.0)*10;
|
2014-06-03 22:32:59 +02:00
|
|
|
uca_org_t init_result = init_interface(&l_ip, name); // init_result is dummy
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
calcWireData();
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
double long_channel_device_reduction =
|
|
|
|
longer_channel_device_reduction(device_ty,core_ty);
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
double sckRation = g_tp.sckt_co_eff;
|
|
|
|
power.readOp.dynamic *= sckRation;
|
|
|
|
power.writeOp.dynamic *= sckRation;
|
|
|
|
power.searchOp.dynamic *= sckRation;
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
power.readOp.longer_channel_leakage =
|
|
|
|
power.readOp.leakage*long_channel_device_reduction;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|