861 lines
26 KiB
C
861 lines
26 KiB
C
/*********************************************************************
|
|
* The following code is part of the power modelling feature of VTR.
|
|
*
|
|
* For support:
|
|
* http://code.google.com/p/vtr-verilog-to-routing/wiki/Power
|
|
*
|
|
* or email:
|
|
* vtr.power.estimation@gmail.com
|
|
*
|
|
* If you are using power estimation for your researach please cite:
|
|
*
|
|
* Jeffrey Goeders and Steven Wilton. VersaPower: Power Estimation
|
|
* for Diverse FPGA Architectures. In International Conference on
|
|
* Field Programmable Technology, 2012.
|
|
*
|
|
********************************************************************/
|
|
|
|
/**
|
|
* The functions in this file are used to count the transistors in the
|
|
* FPGA, for physical size estimations
|
|
*/
|
|
|
|
/************************* INCLUDES *********************************/
|
|
#include <cstring>
|
|
using namespace std;
|
|
|
|
#include <assert.h>
|
|
|
|
#include "power_sizing.h"
|
|
#include "power.h"
|
|
#include "globals.h"
|
|
#include "power_util.h"
|
|
/************************* GLOBALS **********************************/
|
|
static double g_MTA_area;
|
|
|
|
/************************* FUNCTION DELCARATIONS ********************/
|
|
static double power_count_transistors_connectionbox(void);
|
|
static double power_count_transistors_mux(t_mux_arch * mux_arch);
|
|
static double power_count_transistors_mux_node(t_mux_node * mux_node,
|
|
float transistor_size);
|
|
static void power_mux_node_max_inputs(t_mux_node * mux_node,
|
|
float * max_inputs);
|
|
static double power_count_transistors_interc(t_interconnect * interc);
|
|
static double power_count_transistors_pb_node(t_pb_graph_node * pb_node);
|
|
static double power_count_transistors_switchbox(t_arch * arch);
|
|
static double power_count_transistors_primitive(t_pb_type * pb_type);
|
|
static double power_count_transistors_LUT(int LUT_inputs,
|
|
float transistor_size);
|
|
static double power_count_transistors_FF(float size);
|
|
static double power_count_transistor_SRAM_bit(void);
|
|
static double power_count_transistors_inv(float size);
|
|
static double power_count_transistors_trans_gate(float size);
|
|
static double power_count_transistors_levr();
|
|
static double power_MTAs(float size);
|
|
static void power_size_pin_buffers_and_wires(t_pb_graph_pin * pin,
|
|
boolean pin_is_an_input);
|
|
static double power_transistors_for_pb_node(t_pb_graph_node * pb_node);
|
|
static double power_transistors_per_tile(t_arch * arch);
|
|
static void power_size_pb(void);
|
|
static void power_size_pb_rec(t_pb_graph_node * pb_node);
|
|
static void power_size_pin_to_interconnect(t_interconnect * interc,
|
|
int * fanout, float * wirelength);
|
|
static double power_MTAs(float W_size);
|
|
static double power_MTAs_L(float L_size);
|
|
/************************* FUNCTION DEFINITIONS *********************/
|
|
|
|
/**
|
|
* Counts the number of transistors in the largest connection box
|
|
*/
|
|
static double power_count_transistors_connectionbox(void) {
|
|
double transistor_cnt = 0.;
|
|
int CLB_inputs;
|
|
float buffer_size;
|
|
|
|
//assert(FILL_TYPE->pb_graph_head->num_input_ports == 1);
|
|
CLB_inputs = FILL_TYPE->pb_graph_head->num_input_pins[0];
|
|
|
|
/* Buffers from Tracks */
|
|
buffer_size = g_power_commonly_used->max_seg_to_IPIN_fanout
|
|
* (g_power_commonly_used->NMOS_1X_C_d
|
|
/ g_power_commonly_used->INV_1X_C_in)
|
|
/ g_power_arch->logical_effort_factor;
|
|
buffer_size = max(1.0F, buffer_size);
|
|
transistor_cnt += g_solution_inf.channel_width
|
|
* power_count_transistors_buffer(buffer_size);
|
|
|
|
/* Muxes to IPINs */
|
|
transistor_cnt += CLB_inputs
|
|
* power_count_transistors_mux(
|
|
power_get_mux_arch(g_power_commonly_used->max_IPIN_fanin,
|
|
g_power_arch->mux_transistor_size));
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
/**
|
|
* Counts the number of transistors in a buffer.
|
|
* - buffer_size: The final stage size of the buffer, relative to a minimum sized inverter
|
|
*/
|
|
double power_count_transistors_buffer(float buffer_size) {
|
|
int stages;
|
|
float effort;
|
|
float stage_size;
|
|
int stage_idx;
|
|
double transistor_cnt = 0.;
|
|
|
|
stages = power_calc_buffer_num_stages(buffer_size,
|
|
g_power_arch->logical_effort_factor);
|
|
effort = calc_buffer_stage_effort(stages, buffer_size);
|
|
|
|
stage_size = 1;
|
|
for (stage_idx = 0; stage_idx < stages; stage_idx++) {
|
|
transistor_cnt += power_count_transistors_inv(stage_size);
|
|
stage_size *= effort;
|
|
}
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
/**
|
|
* Counts the number of transistors in a multiplexer
|
|
* - mux_arch: The architecture of the multiplexer
|
|
*/
|
|
static double power_count_transistors_mux(t_mux_arch * mux_arch) {
|
|
double transistor_cnt = 0.;
|
|
int lvl_idx;
|
|
float * max_inputs;
|
|
|
|
/* SRAM bits */
|
|
max_inputs = (float*) my_calloc(mux_arch->levels, sizeof(float));
|
|
for (lvl_idx = 0; lvl_idx < mux_arch->levels; lvl_idx++) {
|
|
max_inputs[lvl_idx] = 0.;
|
|
}
|
|
power_mux_node_max_inputs(mux_arch->mux_graph_head, max_inputs);
|
|
|
|
for (lvl_idx = 0; lvl_idx < mux_arch->levels; lvl_idx++) {
|
|
/* Assume there is decoder logic */
|
|
transistor_cnt += ceil(log(max_inputs[lvl_idx]) / log((double) 2.0))
|
|
* power_count_transistor_SRAM_bit();
|
|
|
|
/*
|
|
if (mux_arch->encoding_types[lvl_idx] == ENCODING_DECODER) {
|
|
transistor_cnt += ceil(log2((float)max_inputs[lvl_idx]))
|
|
* power_cnt_transistor_SRAM_bit();
|
|
// TODO - Size of decoder
|
|
} else if (mux_arch->encoding_types[lvl_idx] == ENCODING_ONE_HOT) {
|
|
transistor_cnt += max_inputs[lvl_idx]
|
|
* power_cnt_transistor_SRAM_bit();
|
|
} else {
|
|
assert(0);
|
|
}
|
|
*/
|
|
}
|
|
|
|
transistor_cnt += power_count_transistors_mux_node(mux_arch->mux_graph_head,
|
|
mux_arch->transistor_size);
|
|
free(max_inputs);
|
|
return transistor_cnt;
|
|
}
|
|
|
|
/**
|
|
* This function is used recursively to determine the largest single-level
|
|
* multiplexer at each level of a multi-level multiplexer
|
|
*/
|
|
static void power_mux_node_max_inputs(t_mux_node * mux_node,
|
|
float * max_inputs) {
|
|
|
|
max_inputs[mux_node->level] = max(max_inputs[mux_node->level],
|
|
static_cast<float>(mux_node->num_inputs));
|
|
|
|
if (mux_node->level != 0) {
|
|
int child_idx;
|
|
|
|
for (child_idx = 0; child_idx < mux_node->num_inputs; child_idx++) {
|
|
power_mux_node_max_inputs(&mux_node->children[child_idx],
|
|
max_inputs);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function is used recursively to count the number of transistors in a multiplexer
|
|
*/
|
|
static double power_count_transistors_mux_node(t_mux_node * mux_node,
|
|
float transistor_size) {
|
|
int input_idx;
|
|
double transistor_cnt = 0.;
|
|
|
|
if (mux_node->num_inputs != 1) {
|
|
for (input_idx = 0; input_idx < mux_node->num_inputs; input_idx++) {
|
|
/* Single Pass transistor */
|
|
transistor_cnt += power_MTAs(transistor_size);
|
|
|
|
/* Child MUX */
|
|
if (mux_node->level != 0) {
|
|
transistor_cnt += power_count_transistors_mux_node(
|
|
&mux_node->children[input_idx], transistor_size);
|
|
}
|
|
}
|
|
}
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
/**
|
|
* This function returns the number of transistors in an interconnect structure
|
|
*/
|
|
static double power_count_transistors_interc(t_interconnect * interc) {
|
|
double transistor_cnt = 0.;
|
|
|
|
switch (interc->type) {
|
|
case DIRECT_INTERC:
|
|
/* No transistors */
|
|
break;
|
|
case MUX_INTERC:
|
|
case COMPLETE_INTERC:
|
|
/* Bus based interconnect:
|
|
* - Each output port requires a (num_input_ports:1) bus-based multiplexor.
|
|
* - The number of muxes required for bus based multiplexors is equivalent to
|
|
* the width of the bus (num_pins_per_port).
|
|
*/
|
|
transistor_cnt += interc->interconnect_power->num_output_ports
|
|
* interc->interconnect_power->num_pins_per_port
|
|
* power_count_transistors_mux(
|
|
power_get_mux_arch(
|
|
interc->interconnect_power->num_input_ports,
|
|
g_power_arch->mux_transistor_size));
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
interc->interconnect_power->transistor_cnt = transistor_cnt;
|
|
return transistor_cnt;
|
|
}
|
|
|
|
void power_sizing_init(t_arch * arch) {
|
|
float transistors_per_tile;
|
|
|
|
// tech size = 2 lambda, so lambda^2/4.0 = tech^2
|
|
g_MTA_area = ((POWER_MTA_L * POWER_MTA_W)/ 4.0)*pow(g_power_tech->tech_size,
|
|
(float) 2.0);
|
|
|
|
// Determines physical size of different PBs
|
|
power_size_pb();
|
|
|
|
/* Find # of transistors in each tile type */
|
|
transistors_per_tile = power_transistors_per_tile(arch);
|
|
|
|
/* Calculate CLB tile size
|
|
* - Assume a square tile
|
|
* - Assume min transistor size is Wx6L
|
|
* - Assume an overhead to space transistors
|
|
*/
|
|
g_power_commonly_used->tile_length = sqrt(
|
|
power_transistor_area(transistors_per_tile));
|
|
}
|
|
|
|
/**
|
|
* This functions counts the number of transistors in all structures in the FPGA.
|
|
* It returns the number of transistors in a grid of the FPGA (logic block,
|
|
* switch box, 2 connection boxes)
|
|
*/
|
|
static double power_transistors_per_tile(t_arch * arch) {
|
|
double transistor_cnt = 0.;
|
|
|
|
transistor_cnt += power_transistors_for_pb_node(FILL_TYPE->pb_graph_head);
|
|
|
|
transistor_cnt += 2 * power_count_transistors_switchbox(arch);
|
|
|
|
transistor_cnt += 2 * power_count_transistors_connectionbox();
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
static double power_transistors_for_pb_node(t_pb_graph_node * pb_node) {
|
|
return pb_node->pb_node_power->transistor_cnt_interc
|
|
+ pb_node->pb_node_power->transistor_cnt_pb_children
|
|
+ pb_node->pb_node_power->transistor_cnt_buffers;
|
|
}
|
|
|
|
/**
|
|
* This function counts the number of transistors for a given physical block type
|
|
*/
|
|
static double power_count_transistors_pb_node(t_pb_graph_node * pb_node) {
|
|
int mode_idx;
|
|
int interc;
|
|
int child;
|
|
int pb_idx;
|
|
|
|
double tc_children_max = 0;
|
|
double tc_interc_max = 0;
|
|
boolean ignore_interc = FALSE;
|
|
|
|
t_pb_type * pb_type = pb_node->pb_type;
|
|
|
|
/* Check if this is a leaf node, or whether it has children */
|
|
if (pb_type->num_modes == 0) {
|
|
/* Leaf node */
|
|
tc_interc_max = 0;
|
|
tc_children_max = power_count_transistors_primitive(pb_type);
|
|
} else {
|
|
/* Find max transistor count between all modes */
|
|
for (mode_idx = 0; mode_idx < pb_type->num_modes; mode_idx++) {
|
|
|
|
double tc_children = 0;
|
|
double tc_interc = 0;
|
|
|
|
t_mode * mode = &pb_type->modes[mode_idx];
|
|
|
|
if (pb_type->class_type == LUT_CLASS) {
|
|
/* LUTs will have a child node that is used for routing purposes
|
|
* For the routing algorithms it is completely connected; however,
|
|
* this interconnect does not exist in FPGA hardware and should
|
|
* be ignored for power calculations. */
|
|
ignore_interc = TRUE;
|
|
}
|
|
|
|
/* Count Interconnect Transistors */
|
|
if (!ignore_interc) {
|
|
for (interc = 0; interc < mode->num_interconnect; interc++) {
|
|
tc_interc += power_count_transistors_interc(
|
|
&mode->interconnect[interc]);
|
|
}
|
|
}
|
|
tc_interc_max = max(tc_interc_max, tc_interc);
|
|
|
|
/* Count Child PB Types */
|
|
for (child = 0; child < mode->num_pb_type_children; child++) {
|
|
t_pb_type * child_type = &mode->pb_type_children[child];
|
|
|
|
for (pb_idx = 0; pb_idx < child_type->num_pb; pb_idx++) {
|
|
tc_children +=
|
|
power_transistors_for_pb_node(
|
|
&pb_node->child_pb_graph_nodes[mode_idx][child][pb_idx]);
|
|
}
|
|
}
|
|
|
|
tc_children_max = max(tc_children_max, tc_children);
|
|
}
|
|
}
|
|
|
|
pb_node->pb_node_power->transistor_cnt_interc = tc_interc_max;
|
|
pb_node->pb_node_power->transistor_cnt_pb_children = tc_children_max;
|
|
|
|
return (tc_interc_max + tc_children_max);
|
|
}
|
|
|
|
/**
|
|
* This function counts the maximum number of transistors in a switch box
|
|
*/
|
|
static double power_count_transistors_switchbox(t_arch * arch) {
|
|
double transistor_cnt = 0.;
|
|
double transistors_per_buf_mux = 0.;
|
|
int seg_idx;
|
|
|
|
/* Buffer */
|
|
transistors_per_buf_mux += power_count_transistors_buffer(
|
|
(float) g_power_commonly_used->max_seg_fanout
|
|
/ g_power_arch->logical_effort_factor);
|
|
|
|
/* Multiplexor */
|
|
transistors_per_buf_mux += power_count_transistors_mux(
|
|
power_get_mux_arch(g_power_commonly_used->max_routing_mux_size,
|
|
g_power_arch->mux_transistor_size));
|
|
|
|
for (seg_idx = 0; seg_idx < arch->num_segments; seg_idx++) {
|
|
/* In each switchbox, the different types of segments occur with relative freqencies.
|
|
* Thus the total number of wires of each segment type is (#tracks * freq * 2).
|
|
* The (x2) factor accounts for vertical and horizontal tracks.
|
|
* Of the wires of each segment type only (1/seglength) will have a mux&buffer.
|
|
*/
|
|
float freq_frac = (float) arch->Segments[seg_idx].frequency
|
|
/ (float) MAX_CHANNEL_WIDTH;
|
|
|
|
transistor_cnt += transistors_per_buf_mux * 2 * freq_frac
|
|
* g_solution_inf.channel_width
|
|
* (1 / (float) arch->Segments[seg_idx].length);
|
|
}
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
/**
|
|
* This function calculates the number of transistors for a primitive physical block
|
|
*/
|
|
static double power_count_transistors_primitive(t_pb_type * pb_type) {
|
|
double transistor_cnt;
|
|
|
|
if (strcmp(pb_type->blif_model, ".names") == 0) {
|
|
/* LUT */
|
|
transistor_cnt = power_count_transistors_LUT(pb_type->num_input_pins,
|
|
g_power_arch->LUT_transistor_size);
|
|
} else if (strcmp(pb_type->blif_model, ".latch") == 0) {
|
|
/* Latch */
|
|
transistor_cnt = power_count_transistors_FF(g_power_arch->FF_size);
|
|
} else {
|
|
/* Other */
|
|
char msg[BUFSIZE];
|
|
|
|
sprintf(msg, "No transistor counter function for BLIF model: %s",
|
|
pb_type->blif_model);
|
|
power_log_msg(POWER_LOG_WARNING, msg);
|
|
transistor_cnt = 0;
|
|
}
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
/**
|
|
* Returns the transistor count of an SRAM cell
|
|
*/
|
|
static double power_count_transistor_SRAM_bit(void) {
|
|
return g_power_arch->transistors_per_SRAM_bit;
|
|
}
|
|
|
|
static double power_count_transistors_levr() {
|
|
double transistor_cnt = 0.;
|
|
|
|
/* Each level restorer has a P/N=1/2 inverter and a W/L=1/2 PMOS */
|
|
|
|
/* Inverter */
|
|
transistor_cnt += power_MTAs(2); // NMOS
|
|
transistor_cnt += 1.0; // PMOS
|
|
|
|
/* Pull-up */
|
|
transistor_cnt += power_MTAs_L(2.0); // Double length
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
/**
|
|
* Returns the transistor count for a LUT
|
|
*/
|
|
static double power_count_transistors_LUT(int LUT_inputs,
|
|
float transistor_size) {
|
|
double transistor_cnt = 0.;
|
|
int level_idx;
|
|
|
|
/* Each input driver has 1-1X and 2-2X inverters */
|
|
transistor_cnt += (double) LUT_inputs
|
|
* (power_count_transistors_inv(1.0)
|
|
+ 2 * power_count_transistors_inv(2.0));
|
|
|
|
/* SRAM bits */
|
|
transistor_cnt += power_count_transistor_SRAM_bit() * (1 << LUT_inputs);
|
|
|
|
for (level_idx = 0; level_idx < LUT_inputs; level_idx++) {
|
|
|
|
/* Pass transistors */
|
|
transistor_cnt += (1 << (LUT_inputs - level_idx))
|
|
* power_MTAs(transistor_size);
|
|
|
|
/* Add level restorer after every 2 stages (level_idx %2 == 1)
|
|
* But if there is an odd # of stages, just put one at the last
|
|
* stage (level_idx == LUT_size - 1) and not at the stage just before
|
|
* the last stage (level_idx != LUT_size - 2)
|
|
*/
|
|
if (((level_idx % 2 == 1) && (level_idx != LUT_inputs - 2))
|
|
|| (level_idx == LUT_inputs - 1)) {
|
|
transistor_cnt += power_count_transistors_levr();
|
|
}
|
|
}
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
static double power_count_transistors_trans_gate(float size) {
|
|
double transistor_cnt = 0.;
|
|
|
|
transistor_cnt += power_MTAs(size);
|
|
transistor_cnt += power_MTAs(size * g_power_tech->PN_ratio);
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
static double power_count_transistors_inv(float size) {
|
|
double transistor_cnt = 0.;
|
|
|
|
/* NMOS */
|
|
transistor_cnt += power_MTAs(size);
|
|
|
|
/* PMOS */
|
|
transistor_cnt += power_MTAs(g_power_tech->PN_ratio * size);
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
/**
|
|
* Returns the transistor count for a flip-flop
|
|
*/
|
|
static double power_count_transistors_FF(float size) {
|
|
double transistor_cnt = 0.;
|
|
|
|
/* 4 1X Inverters */
|
|
transistor_cnt += 4 * power_count_transistors_inv(size);
|
|
|
|
/* 2 Muxes = 4 transmission gates */
|
|
transistor_cnt += 4 * power_count_transistors_trans_gate(size);
|
|
|
|
return transistor_cnt;
|
|
}
|
|
|
|
double power_transistor_area(double num_MTAs) {
|
|
return num_MTAs * g_MTA_area;
|
|
}
|
|
|
|
static double power_MTAs(float W_size) {
|
|
return 1 + (W_size - 1) * (POWER_DRC_MIN_W / POWER_MTA_W);
|
|
}
|
|
|
|
static double power_MTAs_L(float L_size) {
|
|
return 1 + (L_size - 1) * (POWER_DRC_MIN_L / POWER_MTA_L);
|
|
}
|
|
|
|
static void power_size_pb(void) {
|
|
int type_idx;
|
|
|
|
for (type_idx = 0; type_idx < num_types; type_idx++) {
|
|
if (type_descriptors[type_idx].pb_graph_head) {
|
|
power_size_pb_rec(type_descriptors[type_idx].pb_graph_head);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void power_size_pb_rec(t_pb_graph_node * pb_node) {
|
|
int port_idx, pin_idx;
|
|
int mode_idx, type_idx, pb_idx;
|
|
boolean size_buffers_and_wires = TRUE;
|
|
|
|
if (!power_method_is_transistor_level(
|
|
pb_node->pb_type->pb_type_power->estimation_method)
|
|
&& pb_node != FILL_TYPE->pb_graph_head) {
|
|
/* Area information is only needed for:
|
|
* 1. Transistor-level estimation methods
|
|
* 2. the FILL_TYPE for tile size calculations
|
|
*/
|
|
return;
|
|
}
|
|
|
|
/* Recursive call for all child pb nodes */
|
|
for (mode_idx = 0; mode_idx < pb_node->pb_type->num_modes; mode_idx++) {
|
|
t_mode * mode = &pb_node->pb_type->modes[mode_idx];
|
|
|
|
for (type_idx = 0; type_idx < mode->num_pb_type_children; type_idx++) {
|
|
int num_pb = mode->pb_type_children[type_idx].num_pb;
|
|
|
|
for (pb_idx = 0; pb_idx < num_pb; pb_idx++) {
|
|
|
|
power_size_pb_rec(
|
|
&pb_node->child_pb_graph_nodes[mode_idx][type_idx][pb_idx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Determine # of transistors for this node */
|
|
power_count_transistors_pb_node(pb_node);
|
|
|
|
if (pb_node->pb_type->class_type == LUT_CLASS) {
|
|
/* LUTs will have a child node that is used for routing purposes
|
|
* For the routing algorithms it is completely connected; however,
|
|
* this interconnect does not exist in FPGA hardware and should
|
|
* be ignored for power calculations. */
|
|
size_buffers_and_wires = FALSE;
|
|
}
|
|
|
|
if (!power_method_is_transistor_level(
|
|
pb_node->pb_type->pb_type_power->estimation_method)) {
|
|
size_buffers_and_wires = FALSE;
|
|
}
|
|
|
|
/* Size all local buffers and wires */
|
|
if (size_buffers_and_wires) {
|
|
for (port_idx = 0; port_idx < pb_node->num_input_ports; port_idx++) {
|
|
for (pin_idx = 0; pin_idx < pb_node->num_input_pins[port_idx];
|
|
pin_idx++) {
|
|
power_size_pin_buffers_and_wires(
|
|
&pb_node->input_pins[port_idx][pin_idx], TRUE);
|
|
}
|
|
}
|
|
|
|
for (port_idx = 0; port_idx < pb_node->num_output_ports; port_idx++) {
|
|
for (pin_idx = 0; pin_idx < pb_node->num_output_pins[port_idx];
|
|
pin_idx++) {
|
|
power_size_pin_buffers_and_wires(
|
|
&pb_node->output_pins[port_idx][pin_idx], FALSE);
|
|
}
|
|
}
|
|
|
|
for (port_idx = 0; port_idx < pb_node->num_clock_ports; port_idx++) {
|
|
for (pin_idx = 0; pin_idx < pb_node->num_clock_pins[port_idx];
|
|
pin_idx++) {
|
|
power_size_pin_buffers_and_wires(
|
|
&pb_node->clock_pins[port_idx][pin_idx], TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* Provides statistics about the connection between the pin and interconnect */
|
|
static void power_size_pin_to_interconnect(t_interconnect * interc,
|
|
int * fanout, float * wirelength) {
|
|
|
|
float this_interc_sidelength;
|
|
|
|
/* Pin to interconnect wirelength */
|
|
switch (interc->type) {
|
|
case DIRECT_INTERC:
|
|
*wirelength = 0;
|
|
*fanout = 1;
|
|
break;
|
|
case MUX_INTERC:
|
|
|
|
case COMPLETE_INTERC:
|
|
/* The sidelength of this crossbar */
|
|
this_interc_sidelength = sqrt(
|
|
power_transistor_area(
|
|
interc->interconnect_power->transistor_cnt));
|
|
|
|
/* Assume that inputs to the crossbar have a structure like this:
|
|
*
|
|
* A B|-----
|
|
* -----|---C-
|
|
* |-----
|
|
*
|
|
* A - wire from pin to point of fanout (grows pb interconnect area)
|
|
* B - fanout wire (sidelength of this crossbar)
|
|
* C - fanouts to crossbar muxes (grows with pb interconnect area)
|
|
*/
|
|
|
|
*fanout = interc->interconnect_power->num_output_ports;
|
|
*wirelength = this_interc_sidelength;
|
|
//*wirelength = ((1 + *fanout) / 2.0) * g_power_arch->local_interc_factor
|
|
// * pb_interc_sidelength + this_interc_sidelength;
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static void power_size_pin_buffers_and_wires(t_pb_graph_pin * pin,
|
|
boolean pin_is_an_input) {
|
|
int edge_idx;
|
|
int list_cnt;
|
|
t_interconnect ** list;
|
|
boolean found;
|
|
int i;
|
|
|
|
float C_load;
|
|
float this_pb_length;
|
|
|
|
int fanout;
|
|
float wirelength_out = 0;
|
|
float wirelength_in = 0;
|
|
|
|
int fanout_tmp;
|
|
float wirelength_tmp;
|
|
|
|
float this_pb_interc_sidelength = 0;
|
|
float parent_pb_interc_sidelength = 0;
|
|
boolean top_level_pb;
|
|
|
|
t_pb_type * this_pb_type = pin->parent_node->pb_type;
|
|
|
|
/*
|
|
if (strcmp(pin->parent_node->pb_type->name, "clb") == 0) {
|
|
//printf("here\n");
|
|
}*/
|
|
|
|
this_pb_interc_sidelength = sqrt(
|
|
power_transistor_area(
|
|
pin->parent_node->pb_node_power->transistor_cnt_interc));
|
|
if (pin->parent_node->parent_pb_graph_node == NULL) {
|
|
top_level_pb = TRUE;
|
|
parent_pb_interc_sidelength = 0.;
|
|
} else {
|
|
top_level_pb = FALSE;
|
|
parent_pb_interc_sidelength =
|
|
sqrt(
|
|
power_transistor_area(
|
|
pin->parent_node->parent_pb_graph_node->pb_node_power->transistor_cnt_interc));
|
|
}
|
|
|
|
/* Pins are connected to a wire that is connected to:
|
|
* 1. Interconnect structures belonging its pb_node, and/or
|
|
* - The pb_node may have one or more modes, each with a set of
|
|
* interconnect. The capacitance is the worst-case capacitance
|
|
* between the different modes.
|
|
*
|
|
* 2. Interconnect structures belonging to its parent pb_node
|
|
*/
|
|
|
|
/* We want to estimate the physical pin fan-out, unfortunately it is not defined in the architecture file.
|
|
* Instead, we know the modes of operation, and the fanout may differ depending on the mode. We assume
|
|
* that the physical fanout is the max of the connections to the various modes (although in reality it could
|
|
* be higher)*/
|
|
|
|
/* Loop through all edges, building a list of interconnect that this pin drives */
|
|
list = NULL;
|
|
list_cnt = 0;
|
|
for (edge_idx = 0; edge_idx < pin->num_output_edges; edge_idx++) {
|
|
/* Check if its already in the list */
|
|
found = FALSE;
|
|
for (i = 0; i < list_cnt; i++) {
|
|
if (list[i] == pin->output_edges[edge_idx]->interconnect) {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
list_cnt++;
|
|
list = (t_interconnect**) my_realloc(list,
|
|
list_cnt * sizeof(t_interconnect*));
|
|
list[list_cnt - 1] = pin->output_edges[edge_idx]->interconnect;
|
|
}
|
|
}
|
|
|
|
/* Determine the:
|
|
* 1. Wirelength connected to the pin
|
|
* 2. Fanout of the pin
|
|
*/
|
|
if (pin_is_an_input) {
|
|
/* Pin is an input to the PB.
|
|
* Thus, all interconnect it drives belong to the modes of the PB.
|
|
*/
|
|
int * fanout_per_mode;
|
|
float * wirelength_out_per_mode;
|
|
|
|
fanout_per_mode = (int*) my_calloc(this_pb_type->num_modes,
|
|
sizeof(int));
|
|
wirelength_out_per_mode = (float *) my_calloc(this_pb_type->num_modes,
|
|
sizeof(float));
|
|
|
|
for (i = 0; i < list_cnt; i++) {
|
|
int mode_idx = list[i]->parent_mode_index;
|
|
|
|
power_size_pin_to_interconnect(list[i], &fanout_tmp,
|
|
&wirelength_tmp);
|
|
|
|
fanout_per_mode[mode_idx] += fanout_tmp;
|
|
wirelength_out_per_mode[mode_idx] += wirelength_tmp;
|
|
}
|
|
|
|
fanout = 0;
|
|
wirelength_out = 0.;
|
|
|
|
/* Find worst-case between modes*/
|
|
for (i = 0; i < this_pb_type->num_modes; i++) {
|
|
fanout = max(fanout, fanout_per_mode[i]);
|
|
wirelength_out = max(wirelength_out, wirelength_out_per_mode[i]);
|
|
}
|
|
if (wirelength_out != 0) {
|
|
wirelength_out += g_power_arch->local_interc_factor
|
|
* this_pb_interc_sidelength;
|
|
}
|
|
|
|
free(fanout_per_mode);
|
|
free(wirelength_out_per_mode);
|
|
|
|
/* Input wirelength - from parent PB */
|
|
if (!top_level_pb) {
|
|
wirelength_in = g_power_arch->local_interc_factor
|
|
* parent_pb_interc_sidelength;
|
|
}
|
|
|
|
} else {
|
|
/* Pin is an output of the PB.
|
|
* Thus, all interconnect it drives belong to the parent PB.
|
|
*/
|
|
fanout = 0;
|
|
wirelength_out = 0.;
|
|
|
|
if (top_level_pb) {
|
|
/* Outputs of top-level pb should not drive interconnect */
|
|
assert(list_cnt == 0);
|
|
}
|
|
|
|
/* Loop through all interconnect that this pin drives */
|
|
|
|
for (i = 0; i < list_cnt; i++) {
|
|
power_size_pin_to_interconnect(list[i], &fanout_tmp,
|
|
&wirelength_tmp);
|
|
fanout += fanout_tmp;
|
|
wirelength_out += wirelength_tmp;
|
|
}
|
|
if (wirelength_out != 0) {
|
|
wirelength_out += g_power_arch->local_interc_factor
|
|
* parent_pb_interc_sidelength;
|
|
}
|
|
|
|
/* Input wirelength - from this PB */
|
|
wirelength_in = g_power_arch->local_interc_factor
|
|
* this_pb_interc_sidelength;
|
|
|
|
}
|
|
free(list);
|
|
|
|
/* Wirelength */
|
|
switch (pin->port->port_power->wire_type) {
|
|
case POWER_WIRE_TYPE_IGNORED:
|
|
/* User is ignoring this wirelength */
|
|
pin->pin_power->C_wire = 0.;
|
|
break;
|
|
case POWER_WIRE_TYPE_C:
|
|
pin->pin_power->C_wire = pin->port->port_power->wire.C;
|
|
break;
|
|
case POWER_WIRE_TYPE_ABSOLUTE_LENGTH:
|
|
pin->pin_power->C_wire = pin->port->port_power->wire.absolute_length
|
|
* g_power_arch->C_wire_local;
|
|
break;
|
|
case POWER_WIRE_TYPE_RELATIVE_LENGTH:
|
|
this_pb_length = sqrt(
|
|
power_transistor_area(
|
|
power_transistors_for_pb_node(pin->parent_node)));
|
|
pin->pin_power->C_wire = pin->port->port_power->wire.relative_length
|
|
* this_pb_length * g_power_arch->C_wire_local;
|
|
break;
|
|
|
|
case POWER_WIRE_TYPE_AUTO:
|
|
pin->pin_power->C_wire += g_power_arch->C_wire_local
|
|
* (wirelength_in + wirelength_out);
|
|
break;
|
|
case POWER_WIRE_TYPE_UNDEFINED:
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
|
|
/* Buffer */
|
|
switch (pin->port->port_power->buffer_type) {
|
|
case POWER_BUFFER_TYPE_NONE:
|
|
/* User assumes no buffer */
|
|
pin->pin_power->buffer_size = 0.;
|
|
break;
|
|
case POWER_BUFFER_TYPE_ABSOLUTE_SIZE:
|
|
pin->pin_power->buffer_size = pin->port->port_power->buffer_size;
|
|
break;
|
|
case POWER_BUFFER_TYPE_AUTO:
|
|
/* Asume the buffer drives the wire & fanout muxes */
|
|
C_load = pin->pin_power->C_wire
|
|
+ (fanout) * g_power_commonly_used->INV_1X_C_in; //g_power_commonly_used->NMOS_1X_C_d;
|
|
if (C_load > g_power_commonly_used->INV_1X_C_in) {
|
|
pin->pin_power->buffer_size = power_buffer_size_from_logical_effort(
|
|
C_load);
|
|
} else {
|
|
pin->pin_power->buffer_size = 0.;
|
|
}
|
|
break;
|
|
case POWER_BUFFER_TYPE_UNDEFINED:
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
pin->parent_node->pb_node_power->transistor_cnt_buffers +=
|
|
power_count_transistors_buffer(pin->pin_power->buffer_size);
|
|
}
|