| /********************************************************************* | |
| * 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); | |
| } |