BroadcastHTree.cc revision 10448
110448Snilay@cs.wisc.edu/* Copyright (c) 2012 Massachusetts Institute of Technology 210448Snilay@cs.wisc.edu * 310448Snilay@cs.wisc.edu * Permission is hereby granted, free of charge, to any person obtaining a copy 410448Snilay@cs.wisc.edu * of this software and associated documentation files (the "Software"), to deal 510448Snilay@cs.wisc.edu * in the Software without restriction, including without limitation the rights 610448Snilay@cs.wisc.edu * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 710448Snilay@cs.wisc.edu * copies of the Software, and to permit persons to whom the Software is 810448Snilay@cs.wisc.edu * furnished to do so, subject to the following conditions: 910448Snilay@cs.wisc.edu * 1010448Snilay@cs.wisc.edu * The above copyright notice and this permission notice shall be included in 1110448Snilay@cs.wisc.edu * all copies or substantial portions of the Software. 1210448Snilay@cs.wisc.edu * 1310448Snilay@cs.wisc.edu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1410448Snilay@cs.wisc.edu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1510448Snilay@cs.wisc.edu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1610448Snilay@cs.wisc.edu * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1710448Snilay@cs.wisc.edu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1810448Snilay@cs.wisc.edu * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 1910448Snilay@cs.wisc.edu * THE SOFTWARE. 2010448Snilay@cs.wisc.edu */ 2110448Snilay@cs.wisc.edu 2210447Snilay@cs.wisc.edu#include "model/electrical/BroadcastHTree.h" 2310447Snilay@cs.wisc.edu 2410447Snilay@cs.wisc.edu#include <cmath> 2510447Snilay@cs.wisc.edu#include <vector> 2610447Snilay@cs.wisc.edu 2710447Snilay@cs.wisc.edu#include "model/PortInfo.h" 2810447Snilay@cs.wisc.edu#include "model/EventInfo.h" 2910447Snilay@cs.wisc.edu#include "model/TransitionInfo.h" 3010447Snilay@cs.wisc.edu#include "model/std_cells/StdCellLib.h" 3110447Snilay@cs.wisc.edu#include "model/std_cells/StdCell.h" 3210447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalLoad.h" 3310447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalDelay.h" 3410447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalDriver.h" 3510447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalTimingTree.h" 3610447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalNet.h" 3710447Snilay@cs.wisc.edu 3810447Snilay@cs.wisc.edunamespace DSENT 3910447Snilay@cs.wisc.edu{ 4010447Snilay@cs.wisc.edu using std::pow; 4110447Snilay@cs.wisc.edu using std::vector; 4210447Snilay@cs.wisc.edu 4310447Snilay@cs.wisc.edu BroadcastHTree::BroadcastHTree(const String& instance_name_, const TechModel* tech_model_) 4410447Snilay@cs.wisc.edu : ElectricalModel(instance_name_, tech_model_) 4510447Snilay@cs.wisc.edu { 4610447Snilay@cs.wisc.edu initParameters(); 4710447Snilay@cs.wisc.edu initProperties(); 4810447Snilay@cs.wisc.edu 4910447Snilay@cs.wisc.edu m_leaf_load_ = NULL; 5010447Snilay@cs.wisc.edu m_leaf_head_driver_ = NULL; 5110447Snilay@cs.wisc.edu m_leaf_head_load_ = NULL; 5210447Snilay@cs.wisc.edu } 5310447Snilay@cs.wisc.edu 5410447Snilay@cs.wisc.edu BroadcastHTree::~BroadcastHTree() 5510447Snilay@cs.wisc.edu { 5610447Snilay@cs.wisc.edu clearPtrVector<StdCell>(&m_repeaters_); 5710447Snilay@cs.wisc.edu clearPtrVector<ElectricalLoad>(&m_repeater_loads_); 5810447Snilay@cs.wisc.edu clearPtrVector<ElectricalTimingTree>(&m_timing_trees_); 5910447Snilay@cs.wisc.edu clearPtrVector<StdCell>(&m_leaf_drivers_); 6010447Snilay@cs.wisc.edu delete m_leaf_load_; 6110447Snilay@cs.wisc.edu delete m_leaf_head_driver_; 6210447Snilay@cs.wisc.edu delete m_leaf_head_load_; 6310447Snilay@cs.wisc.edu } 6410447Snilay@cs.wisc.edu 6510447Snilay@cs.wisc.edu void BroadcastHTree::initParameters() 6610447Snilay@cs.wisc.edu { 6710447Snilay@cs.wisc.edu addParameterName("NumberLevels"); 6810447Snilay@cs.wisc.edu addParameterName("NumberBits"); 6910447Snilay@cs.wisc.edu addParameterName("WireLayer"); 7010447Snilay@cs.wisc.edu addParameterName("WireWidthMultiplier", 1.0); 7110447Snilay@cs.wisc.edu addParameterName("WireSpacingMultiplier", 1.0); 7210447Snilay@cs.wisc.edu return; 7310447Snilay@cs.wisc.edu } 7410447Snilay@cs.wisc.edu 7510447Snilay@cs.wisc.edu void BroadcastHTree::initProperties() 7610447Snilay@cs.wisc.edu { 7710447Snilay@cs.wisc.edu addPropertyName("SitePitch"); 7810447Snilay@cs.wisc.edu addPropertyName("TotalLoadCapPerBit"); 7910447Snilay@cs.wisc.edu return; 8010447Snilay@cs.wisc.edu } 8110447Snilay@cs.wisc.edu 8210447Snilay@cs.wisc.edu BroadcastHTree* BroadcastHTree::clone() const 8310447Snilay@cs.wisc.edu { 8410447Snilay@cs.wisc.edu // TODO 8510447Snilay@cs.wisc.edu return NULL; 8610447Snilay@cs.wisc.edu } 8710447Snilay@cs.wisc.edu 8810447Snilay@cs.wisc.edu void BroadcastHTree::constructModel() 8910447Snilay@cs.wisc.edu { 9010447Snilay@cs.wisc.edu // Get parameters 9110447Snilay@cs.wisc.edu unsigned int number_levels = getParameter("NumberLevels").toUInt(); 9210447Snilay@cs.wisc.edu unsigned int number_bits = getParameter("NumberBits").toUInt(); 9310447Snilay@cs.wisc.edu const String& wire_layer = getParameter("WireLayer"); 9410447Snilay@cs.wisc.edu double wire_width_multiplier = getParameter("WireWidthMultiplier").toDouble(); 9510447Snilay@cs.wisc.edu double wire_spacing_multiplier = getParameter("WireSpacingMultiplier").toDouble(); 9610447Snilay@cs.wisc.edu 9710447Snilay@cs.wisc.edu ASSERT(number_levels > 0, "[Error] " + getInstanceName() + 9810447Snilay@cs.wisc.edu " -> Number of levels must be > 0!"); 9910447Snilay@cs.wisc.edu ASSERT(number_bits > 0, "[Error] " + getInstanceName() + 10010447Snilay@cs.wisc.edu " -> Number of bits must be > 0!"); 10110447Snilay@cs.wisc.edu ASSERT(getTechModel()->isWireLayerExist(wire_layer), "[Error] " + getInstanceName() + 10210447Snilay@cs.wisc.edu " -> Wire layer does not exist!"); 10310447Snilay@cs.wisc.edu ASSERT(wire_width_multiplier >= 1.0, "[Error] " + getInstanceName() + 10410447Snilay@cs.wisc.edu " -> Wire width multiplier must be >= 1.0!"); 10510447Snilay@cs.wisc.edu ASSERT(wire_spacing_multiplier >= 1.0, "[Error] " + getInstanceName() + 10610447Snilay@cs.wisc.edu " -> Wire spacing multiplier must be >= 1.0!"); 10710447Snilay@cs.wisc.edu 10810447Snilay@cs.wisc.edu double wire_min_width = getTechModel()->get("Wire->" + wire_layer + "->MinWidth").toDouble(); 10910447Snilay@cs.wisc.edu double wire_min_spacing = getTechModel()->get("Wire->" + wire_layer + "->MinSpacing").toDouble(); 11010447Snilay@cs.wisc.edu 11110447Snilay@cs.wisc.edu double wire_width = wire_min_width * wire_width_multiplier; 11210447Snilay@cs.wisc.edu double wire_spacing = wire_min_spacing * wire_spacing_multiplier; 11310447Snilay@cs.wisc.edu 11410447Snilay@cs.wisc.edu double wire_cap_per_len = getTechModel()->calculateWireCapacitance(wire_layer, wire_width, wire_spacing, 1.0); 11510447Snilay@cs.wisc.edu double wire_res_per_len = getTechModel()->calculateWireResistance(wire_layer, wire_width, 1.0); 11610447Snilay@cs.wisc.edu 11710447Snilay@cs.wisc.edu getGenProperties()->set("WireWidth", wire_width); 11810447Snilay@cs.wisc.edu getGenProperties()->set("WireSpacing", wire_spacing); 11910447Snilay@cs.wisc.edu getGenProperties()->set("WireCapacitancePerLength", wire_cap_per_len); 12010447Snilay@cs.wisc.edu getGenProperties()->set("WireResistancePerLength", wire_res_per_len); 12110447Snilay@cs.wisc.edu 12210447Snilay@cs.wisc.edu // Create ports 12310447Snilay@cs.wisc.edu createInputPort("In", makeNetIndex(0, number_bits-1)); 12410447Snilay@cs.wisc.edu createOutputPort("Out", makeNetIndex(0, number_bits-1)); 12510447Snilay@cs.wisc.edu 12610447Snilay@cs.wisc.edu // Create connections 12710447Snilay@cs.wisc.edu createNet("InTmp"); 12810447Snilay@cs.wisc.edu createNet("OutTmp"); 12910447Snilay@cs.wisc.edu assignVirtualFanin("InTmp", "In"); 13010447Snilay@cs.wisc.edu assignVirtualFanout("Out", "OutTmp"); 13110447Snilay@cs.wisc.edu 13210447Snilay@cs.wisc.edu createLoad("In_Cap"); 13310447Snilay@cs.wisc.edu createDelay("In_to_Out_delay"); 13410447Snilay@cs.wisc.edu 13510447Snilay@cs.wisc.edu ElectricalLoad* in_cap = getLoad("In_Cap"); 13610447Snilay@cs.wisc.edu ElectricalDelay* in_to_out_delay = getDelay("In_to_Out_delay"); 13710447Snilay@cs.wisc.edu 13810447Snilay@cs.wisc.edu getNet("InTmp")->addDownstreamNode(in_cap); 13910447Snilay@cs.wisc.edu in_cap->addDownstreamNode(in_to_out_delay); 14010447Snilay@cs.wisc.edu 14110447Snilay@cs.wisc.edu // Init 14210447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_levels; ++i) 14310447Snilay@cs.wisc.edu { 14410447Snilay@cs.wisc.edu StdCell* repeater = getTechModel()->getStdCellLib()->createStdCell("INV", "Repeater" + (String)i); 14510447Snilay@cs.wisc.edu ElectricalLoad* repeater_load = new ElectricalLoad("RepeaterIn_Cap" + (String)i, this); 14610447Snilay@cs.wisc.edu ElectricalTimingTree* timing_tree = new ElectricalTimingTree("RepeatedLink" + (String)i, this); 14710447Snilay@cs.wisc.edu 14810447Snilay@cs.wisc.edu repeater->construct(); 14910447Snilay@cs.wisc.edu repeater->getNet("Y")->addDownstreamNode(repeater_load); 15010447Snilay@cs.wisc.edu m_repeaters_.push_back(repeater); 15110447Snilay@cs.wisc.edu m_repeater_loads_.push_back(repeater_load); 15210447Snilay@cs.wisc.edu m_timing_trees_.push_back(timing_tree); 15310447Snilay@cs.wisc.edu } 15410447Snilay@cs.wisc.edu 15510447Snilay@cs.wisc.edu // Create area, power, and event results 15610447Snilay@cs.wisc.edu createElectricalAtomicResults(); 15710447Snilay@cs.wisc.edu createElectricalEventResult("Send"); 15810447Snilay@cs.wisc.edu addEventResult(new AtomicResult("DriveLoad")); 15910447Snilay@cs.wisc.edu addEventResult(new AtomicResult("DriveTree")); 16010447Snilay@cs.wisc.edu 16110447Snilay@cs.wisc.edu getEventResult("Send")->addSubResult(getEventResult("DriveLoad"), "Self", 1.0); 16210447Snilay@cs.wisc.edu getEventResult("Send")->addSubResult(getEventResult("DriveTree"), "Self", 1.0); 16310447Snilay@cs.wisc.edu return; 16410447Snilay@cs.wisc.edu } 16510447Snilay@cs.wisc.edu 16610447Snilay@cs.wisc.edu void BroadcastHTree::updateModel() 16710447Snilay@cs.wisc.edu { 16810447Snilay@cs.wisc.edu // Get properties 16910447Snilay@cs.wisc.edu double site_pitch = getProperty("SitePitch").toDouble(); 17010447Snilay@cs.wisc.edu double total_load_cap_per_bit = getProperty("TotalLoadCapPerBit").toDouble(); 17110447Snilay@cs.wisc.edu 17210447Snilay@cs.wisc.edu ASSERT(site_pitch > 0, "[Error] " + getInstanceName() + 17310447Snilay@cs.wisc.edu " -> Site pitch must be > 0!"); 17410447Snilay@cs.wisc.edu ASSERT(total_load_cap_per_bit >= 0.0, "[Error] " + getInstanceName() + 17510447Snilay@cs.wisc.edu " -> Total load capacitance per bit must be >= 0!"); 17610447Snilay@cs.wisc.edu 17710447Snilay@cs.wisc.edu // Get parameters 17810447Snilay@cs.wisc.edu unsigned int number_levels = getParameter("NumberLevels"); 17910447Snilay@cs.wisc.edu unsigned int number_bits = getParameter("NumberBits"); 18010447Snilay@cs.wisc.edu 18110447Snilay@cs.wisc.edu const String& wire_layer = getParameter("WireLayer"); 18210447Snilay@cs.wisc.edu double wire_width = getGenProperties()->get("WireWidth").toDouble(); 18310447Snilay@cs.wisc.edu double wire_spacing = getGenProperties()->get("WireSpacing").toDouble(); 18410447Snilay@cs.wisc.edu double wire_cap_per_len = getGenProperties()->get("WireCapacitancePerLength").toDouble(); 18510447Snilay@cs.wisc.edu double wire_res_per_len = getGenProperties()->get("WireResistancePerLength").toDouble(); 18610447Snilay@cs.wisc.edu 18710447Snilay@cs.wisc.edu double leaf_load_cap = total_load_cap_per_bit / pow(2.0, (double)(number_levels-1)); 18810447Snilay@cs.wisc.edu 18910447Snilay@cs.wisc.edu vector<double> wire_caps(number_levels, 0.0); 19010447Snilay@cs.wisc.edu vector<double> wire_ress(number_levels, 0.0); 19110447Snilay@cs.wisc.edu double wire_length = site_pitch / 2.0; 19210447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_levels; ++i) 19310447Snilay@cs.wisc.edu { 19410447Snilay@cs.wisc.edu wire_caps[i] = wire_cap_per_len * wire_length; 19510447Snilay@cs.wisc.edu wire_ress[i] = wire_res_per_len * wire_length; 19610447Snilay@cs.wisc.edu wire_length /= 2.0; 19710447Snilay@cs.wisc.edu } 19810447Snilay@cs.wisc.edu 19910447Snilay@cs.wisc.edu // Start sizing each stage of repeaters for a transition times. TODO: Find a heuristic about 20010447Snilay@cs.wisc.edu // how the transition time is done...place and route tools make this user-specified 20110447Snilay@cs.wisc.edu double required_transition = 40e-12; 20210447Snilay@cs.wisc.edu m_number_segments_.resize(number_levels, 1); 20310447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_levels; ++i) 20410447Snilay@cs.wisc.edu { 20510447Snilay@cs.wisc.edu Log::printLine(getInstanceName() + " -> Beginning Repeater Insertion " + (String)i); 20610447Snilay@cs.wisc.edu 20710447Snilay@cs.wisc.edu double transition; 20810447Snilay@cs.wisc.edu unsigned int iteration = 0; 20910447Snilay@cs.wisc.edu m_repeaters_[i]->setMinDrivingStrength(); 21010447Snilay@cs.wisc.edu m_repeaters_[i]->getNet("Y")->setDistributedCap(wire_caps[i] / m_number_segments_[i]); 21110447Snilay@cs.wisc.edu m_repeaters_[i]->getNet("Y")->setDistributedRes(wire_ress[i] / m_number_segments_[i]); 21210447Snilay@cs.wisc.edu m_repeater_loads_[i]->setLoadCap(m_repeaters_[i]->getNet("A")->getTotalDownstreamCap()); 21310447Snilay@cs.wisc.edu 21410447Snilay@cs.wisc.edu transition = m_timing_trees_[i]->calculateNodeTransition(m_repeaters_[i]->getNet("Y")); 21510447Snilay@cs.wisc.edu 21610447Snilay@cs.wisc.edu while(required_transition < transition) 21710447Snilay@cs.wisc.edu { 21810447Snilay@cs.wisc.edu Log::printLine(getInstanceName() + " -> Repeater Insertion Iteration " + (String)iteration + 21910447Snilay@cs.wisc.edu ": Required transition = " + (String)required_transition + 22010447Snilay@cs.wisc.edu ", Transition = " + (String)transition + 22110447Snilay@cs.wisc.edu ", Slack = " + (String)(required_transition - transition) + 22210447Snilay@cs.wisc.edu ", Number of repeaters = " + (String)m_number_segments_[i]); 22310447Snilay@cs.wisc.edu 22410447Snilay@cs.wisc.edu // Size up if transition is not met 22510447Snilay@cs.wisc.edu while(required_transition < transition) 22610447Snilay@cs.wisc.edu { 22710447Snilay@cs.wisc.edu if(m_repeaters_[i]->hasMaxDrivingStrength()) 22810447Snilay@cs.wisc.edu { 22910447Snilay@cs.wisc.edu break; 23010447Snilay@cs.wisc.edu } 23110447Snilay@cs.wisc.edu m_repeaters_[i]->increaseDrivingStrength(); 23210447Snilay@cs.wisc.edu m_repeater_loads_[i]->setLoadCap(m_repeaters_[i]->getNet("A")->getTotalDownstreamCap()); 23310447Snilay@cs.wisc.edu transition = m_timing_trees_[i]->calculateNodeTransition(m_repeaters_[i]->getNet("Y")); 23410447Snilay@cs.wisc.edu 23510447Snilay@cs.wisc.edu iteration++; 23610447Snilay@cs.wisc.edu Log::printLine(getInstanceName() + " -> Slack: " + (String)(required_transition - transition)); 23710447Snilay@cs.wisc.edu } 23810447Snilay@cs.wisc.edu // Increase number of segments if thansition is not met 23910447Snilay@cs.wisc.edu if(required_transition < transition) 24010447Snilay@cs.wisc.edu { 24110447Snilay@cs.wisc.edu m_number_segments_[i]++; 24210447Snilay@cs.wisc.edu m_repeaters_[i]->setMinDrivingStrength(); 24310447Snilay@cs.wisc.edu m_repeaters_[i]->getNet("Y")->setDistributedCap(wire_caps[i] / m_number_segments_[i]); 24410447Snilay@cs.wisc.edu m_repeaters_[i]->getNet("Y")->setDistributedRes(wire_ress[i] / m_number_segments_[i]); 24510447Snilay@cs.wisc.edu m_repeater_loads_[i]->setLoadCap(m_repeaters_[i]->getNet("A")->getTotalDownstreamCap()); 24610447Snilay@cs.wisc.edu transition = m_timing_trees_[i]->calculateNodeTransition(m_repeaters_[i]->getNet("Y")); 24710447Snilay@cs.wisc.edu } 24810447Snilay@cs.wisc.edu } 24910447Snilay@cs.wisc.edu Log::printLine(getInstanceName() + " -> Repeater Insertion " + (String)i + " Ended after Iteration: " + (String)iteration + 25010447Snilay@cs.wisc.edu ": Required transition = " + (String)required_transition + 25110447Snilay@cs.wisc.edu ", Transition = " + (String)transition + 25210447Snilay@cs.wisc.edu ", Slack = " + (String)(required_transition - transition) + 25310447Snilay@cs.wisc.edu ", Number of repeaters = " + (String)m_number_segments_[i]); 25410447Snilay@cs.wisc.edu } 25510447Snilay@cs.wisc.edu 25610447Snilay@cs.wisc.edu // Insert inverters to ensure the transition time at the leaf 25710447Snilay@cs.wisc.edu int min_driving_strength_idx = m_repeaters_[number_levels-1]->getDrivingStrengthIdx(); 25810447Snilay@cs.wisc.edu 25910447Snilay@cs.wisc.edu // Remove everything and rebuild again 26010447Snilay@cs.wisc.edu clearPtrVector<StdCell>(&m_leaf_drivers_); 26110447Snilay@cs.wisc.edu delete m_leaf_load_; 26210447Snilay@cs.wisc.edu delete m_leaf_head_driver_; 26310447Snilay@cs.wisc.edu delete m_leaf_head_load_; 26410447Snilay@cs.wisc.edu 26510447Snilay@cs.wisc.edu m_leaf_head_driver_ = getTechModel()->getStdCellLib()->createStdCell("INV", "LeafHeadDriver"); 26610447Snilay@cs.wisc.edu m_leaf_head_driver_->construct(); 26710447Snilay@cs.wisc.edu m_leaf_head_driver_->setDrivingStrengthIdx(min_driving_strength_idx); 26810447Snilay@cs.wisc.edu 26910447Snilay@cs.wisc.edu m_leaf_head_load_ = new ElectricalLoad("LeafHead_Cap", this); 27010447Snilay@cs.wisc.edu m_leaf_head_driver_->getNet("Y")->addDownstreamNode(m_leaf_head_load_); 27110447Snilay@cs.wisc.edu 27210447Snilay@cs.wisc.edu m_leaf_load_ = new ElectricalLoad("Leaf_Cap", this); 27310447Snilay@cs.wisc.edu m_leaf_load_->setLoadCap(leaf_load_cap); 27410447Snilay@cs.wisc.edu 27510447Snilay@cs.wisc.edu StdCell* inv = getTechModel()->getStdCellLib()->createStdCell("INV", "LeafDriver0"); 27610447Snilay@cs.wisc.edu inv->construct(); 27710447Snilay@cs.wisc.edu inv->getNet("Y")->addDownstreamNode(m_leaf_load_); 27810447Snilay@cs.wisc.edu inv->setDrivingStrengthIdx(min_driving_strength_idx); 27910447Snilay@cs.wisc.edu m_leaf_drivers_.push_back(inv); 28010447Snilay@cs.wisc.edu 28110447Snilay@cs.wisc.edu m_leaf_head_load_->setLoadCap(m_leaf_drivers_[0]->getNet("A")->getTotalDownstreamCap()); 28210447Snilay@cs.wisc.edu 28310447Snilay@cs.wisc.edu // Start inserting the buffers 28410447Snilay@cs.wisc.edu ElectricalTimingTree t2("LeafHead", m_leaf_head_driver_); 28510447Snilay@cs.wisc.edu int curr_driver = 0; 28610447Snilay@cs.wisc.edu unsigned int iteration = 0; 28710447Snilay@cs.wisc.edu while(true) 28810447Snilay@cs.wisc.edu { 28910447Snilay@cs.wisc.edu ElectricalTimingTree t("LeafDriver", m_leaf_drivers_[curr_driver]); 29010447Snilay@cs.wisc.edu double transition = t.calculateNodeTransition(m_leaf_drivers_[curr_driver]->getNet("Y")); 29110447Snilay@cs.wisc.edu Log::printLine(getInstanceName() + " -> Buffer Insertion : " + (String)iteration + 29210447Snilay@cs.wisc.edu ": Required transition = " + (String)required_transition + 29310447Snilay@cs.wisc.edu ", Transition = " + (String)transition + 29410447Snilay@cs.wisc.edu ", Slack = " + (String)(required_transition - transition) + 29510447Snilay@cs.wisc.edu ", Number of buffers = " + (String)(curr_driver+1)); 29610447Snilay@cs.wisc.edu 29710447Snilay@cs.wisc.edu // Size up the inverter at curr_driver so that it could drive the next stage 29810447Snilay@cs.wisc.edu while(required_transition < transition) 29910447Snilay@cs.wisc.edu { 30010447Snilay@cs.wisc.edu if(m_leaf_drivers_[curr_driver]->hasMaxDrivingStrength()) 30110447Snilay@cs.wisc.edu { 30210447Snilay@cs.wisc.edu const String& warning_msg = "[Warning] " + getInstanceName() + " -> Transition not met" + 30310447Snilay@cs.wisc.edu ": Required transition = " + (String)required_transition + 30410447Snilay@cs.wisc.edu ", Transition = " + (String)transition + 30510447Snilay@cs.wisc.edu ", Slack = " + (String)(required_transition - transition); 30610447Snilay@cs.wisc.edu Log::printLine(std::cerr, warning_msg); 30710447Snilay@cs.wisc.edu break; 30810447Snilay@cs.wisc.edu } 30910447Snilay@cs.wisc.edu m_leaf_drivers_[curr_driver]->increaseDrivingStrength(); 31010447Snilay@cs.wisc.edu transition = t.calculateNodeTransition(m_leaf_drivers_[curr_driver]->getNet("Y")); 31110447Snilay@cs.wisc.edu iteration++; 31210447Snilay@cs.wisc.edu } 31310447Snilay@cs.wisc.edu // Add an additional inverter if the transition for the first stage does not meet the required transition 31410447Snilay@cs.wisc.edu m_leaf_head_load_->setLoadCap(m_leaf_drivers_[curr_driver]->getNet("A")->getTotalDownstreamCap()); 31510447Snilay@cs.wisc.edu transition = t2.calculateNodeTransition(m_leaf_head_driver_->getNet("Y")); 31610447Snilay@cs.wisc.edu if(required_transition < transition) 31710447Snilay@cs.wisc.edu { 31810447Snilay@cs.wisc.edu inv = getTechModel()->getStdCellLib()->createStdCell("INV", "LeafDriver" + (String)(curr_driver+1)); 31910447Snilay@cs.wisc.edu inv->construct(); 32010447Snilay@cs.wisc.edu inv->getNet("Y")->addDownstreamNode(m_leaf_drivers_[curr_driver]->getNet("A")); 32110447Snilay@cs.wisc.edu inv->setDrivingStrengthIdx(min_driving_strength_idx); 32210447Snilay@cs.wisc.edu m_leaf_drivers_.push_back(inv); 32310447Snilay@cs.wisc.edu curr_driver++; 32410447Snilay@cs.wisc.edu } 32510447Snilay@cs.wisc.edu else 32610447Snilay@cs.wisc.edu { 32710447Snilay@cs.wisc.edu Log::printLine(getInstanceName() + " -> Buffer Insertion Ended after Iteration: " + (String)iteration + 32810447Snilay@cs.wisc.edu ", Number of buffers = " + (String)(curr_driver+1)); 32910447Snilay@cs.wisc.edu break; 33010447Snilay@cs.wisc.edu } 33110447Snilay@cs.wisc.edu } 33210447Snilay@cs.wisc.edu 33310447Snilay@cs.wisc.edu 33410447Snilay@cs.wisc.edu // Update electrical interfaces 33510447Snilay@cs.wisc.edu getLoad("In_Cap")->setLoadCap(m_repeaters_[0]->getNet("A")->getTotalDownstreamCap()); 33610447Snilay@cs.wisc.edu // TODO 33710447Snilay@cs.wisc.edu getDelay("In_to_Out_delay")->setDelay(0.0); 33810447Snilay@cs.wisc.edu 33910447Snilay@cs.wisc.edu // Reset all the atomic results to 0 before start updating new results 34010447Snilay@cs.wisc.edu resetElectricalAtomicResults(); 34110447Snilay@cs.wisc.edu 34210447Snilay@cs.wisc.edu // Update area, power results 34310447Snilay@cs.wisc.edu double wire_area = 0.0; 34410447Snilay@cs.wisc.edu wire_length = site_pitch / 2.0; 34510447Snilay@cs.wisc.edu unsigned int number_branches = 1; 34610447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_levels; ++i) 34710447Snilay@cs.wisc.edu { 34810447Snilay@cs.wisc.edu wire_area += wire_length * (wire_width + wire_spacing) * number_branches * number_bits; 34910447Snilay@cs.wisc.edu addElecticalAtomicResultValues(m_repeaters_[i], m_number_segments_[i] * number_branches * number_bits); 35010447Snilay@cs.wisc.edu wire_length /= 2.0; 35110447Snilay@cs.wisc.edu number_branches *= 2; 35210447Snilay@cs.wisc.edu } 35310447Snilay@cs.wisc.edu number_branches = (unsigned int)pow(2.0, (double)number_levels-1); 35410447Snilay@cs.wisc.edu addElecticalAtomicResultValues(m_leaf_head_driver_, number_branches * number_bits); 35510447Snilay@cs.wisc.edu for(unsigned int i = 0; i < m_leaf_drivers_.size(); ++i) 35610447Snilay@cs.wisc.edu { 35710447Snilay@cs.wisc.edu addElecticalAtomicResultValues(m_leaf_drivers_[i], number_branches * number_bits); 35810447Snilay@cs.wisc.edu } 35910447Snilay@cs.wisc.edu addElecticalWireAtomicResultValue(wire_layer, wire_area); 36010447Snilay@cs.wisc.edu 36110447Snilay@cs.wisc.edu return; 36210447Snilay@cs.wisc.edu } 36310447Snilay@cs.wisc.edu 36410447Snilay@cs.wisc.edu void BroadcastHTree::useModel() 36510447Snilay@cs.wisc.edu { 36610447Snilay@cs.wisc.edu unsigned int number_bits = getParameter("NumberBits").toUInt(); 36710447Snilay@cs.wisc.edu unsigned int number_levels = getParameter("NumberLevels").toUInt(); 36810447Snilay@cs.wisc.edu 36910447Snilay@cs.wisc.edu // Update the transition information for the modeled repeaters 37010447Snilay@cs.wisc.edu // Since we only modeled one repeater. So the transition information for 0->0 and 1->1 37110447Snilay@cs.wisc.edu // is averaged out 37210447Snilay@cs.wisc.edu const TransitionInfo& trans_In = getInputPort("In")->getTransitionInfo(); 37310447Snilay@cs.wisc.edu double average_static_transition = (trans_In.getNumberTransitions00() + trans_In.getNumberTransitions11()) / 2.0; 37410447Snilay@cs.wisc.edu TransitionInfo mod_trans_In(average_static_transition, trans_In.getNumberTransitions01(), average_static_transition); 37510447Snilay@cs.wisc.edu 37610447Snilay@cs.wisc.edu // Propagate the transition information 37710447Snilay@cs.wisc.edu propagateTransitionInfo(); 37810447Snilay@cs.wisc.edu 37910447Snilay@cs.wisc.edu // Update leakage and event 38010447Snilay@cs.wisc.edu double energy = 0.0; 38110447Snilay@cs.wisc.edu double power = 0.0; 38210447Snilay@cs.wisc.edu unsigned int number_branches = 1; 38310447Snilay@cs.wisc.edu for(unsigned int i = 0; i < number_levels; ++i) 38410447Snilay@cs.wisc.edu { 38510447Snilay@cs.wisc.edu assignPortTransitionInfo(m_repeaters_[i], "A", mod_trans_In); 38610447Snilay@cs.wisc.edu m_repeaters_[i]->use(); 38710447Snilay@cs.wisc.edu power += m_repeaters_[i]->getNddPowerResult("Leakage")->calculateSum() * m_number_segments_[i] * number_branches; 38810447Snilay@cs.wisc.edu energy += m_repeaters_[i]->getEventResult("INV")->calculateSum() * m_number_segments_[i] * number_branches; 38910447Snilay@cs.wisc.edu number_branches *= 2; 39010447Snilay@cs.wisc.edu } 39110447Snilay@cs.wisc.edu energy *= number_bits; 39210447Snilay@cs.wisc.edu getEventResult("DriveTree")->setValue(energy); 39310447Snilay@cs.wisc.edu 39410447Snilay@cs.wisc.edu energy = 0.0; 39510447Snilay@cs.wisc.edu assignPortTransitionInfo(m_leaf_head_driver_, "A", mod_trans_In); 39610447Snilay@cs.wisc.edu m_leaf_head_driver_->use(); 39710447Snilay@cs.wisc.edu number_branches = (unsigned int)pow(2.0, (double)number_levels-1); 39810447Snilay@cs.wisc.edu power += m_leaf_head_driver_->getNddPowerResult("Leakage")->calculateSum() * number_branches; 39910447Snilay@cs.wisc.edu energy += m_leaf_head_driver_->getEventResult("INV")->calculateSum() * number_branches; 40010447Snilay@cs.wisc.edu for(unsigned int i = 0; i < m_leaf_drivers_.size(); ++i) 40110447Snilay@cs.wisc.edu { 40210447Snilay@cs.wisc.edu assignPortTransitionInfo(m_leaf_drivers_[i], "A", mod_trans_In); 40310447Snilay@cs.wisc.edu m_leaf_drivers_[i]->use(); 40410447Snilay@cs.wisc.edu power += m_leaf_drivers_[i]->getNddPowerResult("Leakage")->calculateSum() * number_branches; 40510447Snilay@cs.wisc.edu energy += m_leaf_drivers_[i]->getEventResult("INV")->calculateSum() * number_branches; 40610447Snilay@cs.wisc.edu } 40710447Snilay@cs.wisc.edu power *= number_bits; 40810447Snilay@cs.wisc.edu energy *= number_bits; 40910447Snilay@cs.wisc.edu getEventResult("DriveLoad")->setValue(energy); 41010447Snilay@cs.wisc.edu getNddPowerResult("Leakage")->setValue(power); 41110447Snilay@cs.wisc.edu 41210447Snilay@cs.wisc.edu return; 41310447Snilay@cs.wisc.edu } 41410447Snilay@cs.wisc.edu 41510447Snilay@cs.wisc.edu void BroadcastHTree::propagateTransitionInfo() 41610447Snilay@cs.wisc.edu { 41710447Snilay@cs.wisc.edu propagatePortTransitionInfo("Out", "In"); 41810447Snilay@cs.wisc.edu return; 41910447Snilay@cs.wisc.edu } 42010447Snilay@cs.wisc.edu} // namespace DSENT 42110447Snilay@cs.wisc.edu 422