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