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/ElectricalModel.h"
2310447Snilay@cs.wisc.edu
2410447Snilay@cs.wisc.edu#include "model/PortInfo.h"
2510447Snilay@cs.wisc.edu#include "model/EventInfo.h"
2610447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalDriver.h"
2710447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalDriverMultiplier.h"
2810447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalNet.h"
2910447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalLoad.h"
3010447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalDelay.h"
3110447Snilay@cs.wisc.edu
3210447Snilay@cs.wisc.edunamespace DSENT
3310447Snilay@cs.wisc.edu{
3410447Snilay@cs.wisc.edu    ElectricalModel::ElectricalModel(const String& instance_name_, const TechModel* tech_model_)
3510447Snilay@cs.wisc.edu        : Model(instance_name_, tech_model_)
3610447Snilay@cs.wisc.edu    {
3710447Snilay@cs.wisc.edu        m_curr_driving_strengths_idx_ = -1;
3810447Snilay@cs.wisc.edu        m_input_ports_ = new Map<PortInfo*>;
3910447Snilay@cs.wisc.edu        m_output_ports_ = new Map<PortInfo*>;
4010447Snilay@cs.wisc.edu        m_net_references_ = new Map<NetIndex>;
4110447Snilay@cs.wisc.edu        m_drivers_ = new Map<ElectricalDriver*>;
4210447Snilay@cs.wisc.edu        m_driver_multipliers_ = new Map<ElectricalDriverMultiplier*>;
4310447Snilay@cs.wisc.edu        m_nets_ = new Map<ElectricalNet*>;
4410447Snilay@cs.wisc.edu        m_loads_ = new Map<ElectricalLoad*>;
4510447Snilay@cs.wisc.edu        m_delays_ = new Map<ElectricalDelay*>;
4610447Snilay@cs.wisc.edu        m_event_infos_ = new Map<EventInfo*>;
4710447Snilay@cs.wisc.edu    }
4810447Snilay@cs.wisc.edu
4910447Snilay@cs.wisc.edu    ElectricalModel::~ElectricalModel()
5010447Snilay@cs.wisc.edu    {
5110447Snilay@cs.wisc.edu        deletePtrMap<PortInfo>(m_input_ports_);
5210447Snilay@cs.wisc.edu        deletePtrMap<PortInfo>(m_output_ports_);
5310447Snilay@cs.wisc.edu        delete m_net_references_;
5410447Snilay@cs.wisc.edu        deletePtrMap<ElectricalDriver>(m_drivers_);
5510447Snilay@cs.wisc.edu        deletePtrMap<ElectricalDriverMultiplier>(m_driver_multipliers_);
5610447Snilay@cs.wisc.edu        deletePtrMap<ElectricalNet>(m_nets_);
5710447Snilay@cs.wisc.edu        deletePtrMap<ElectricalLoad>(m_loads_);
5810447Snilay@cs.wisc.edu        deletePtrMap<ElectricalDelay>(m_delays_);
5910447Snilay@cs.wisc.edu        deletePtrMap<EventInfo>(m_event_infos_);
6010447Snilay@cs.wisc.edu        m_input_ports_ = NULL;
6110447Snilay@cs.wisc.edu        m_output_ports_ = NULL;
6210447Snilay@cs.wisc.edu        m_net_references_ = NULL;
6310447Snilay@cs.wisc.edu        m_drivers_ = NULL;
6410447Snilay@cs.wisc.edu        m_driver_multipliers_ = NULL;
6510447Snilay@cs.wisc.edu        m_nets_ = NULL;
6610447Snilay@cs.wisc.edu        m_loads_ = NULL;
6710447Snilay@cs.wisc.edu        m_net_references_ = NULL;
6810447Snilay@cs.wisc.edu        m_event_infos_ = NULL;
6910447Snilay@cs.wisc.edu    }
7010447Snilay@cs.wisc.edu
7110447Snilay@cs.wisc.edu    void ElectricalModel::checkProperties() const
7210447Snilay@cs.wisc.edu    {
7310447Snilay@cs.wisc.edu        // Check if the specified driving strength exists in the available driving strengths
7410447Snilay@cs.wisc.edu        if(getProperties()->keyExist("DrivingStrength"))
7510447Snilay@cs.wisc.edu        {
7610447Snilay@cs.wisc.edu            const double driving_strength = getProperty("DrivingStrength");
7710447Snilay@cs.wisc.edu            bool is_found = false;
7810447Snilay@cs.wisc.edu            for(int i = 0; i < (int)m_driving_strengths_.size(); ++i)
7910447Snilay@cs.wisc.edu            {
8010447Snilay@cs.wisc.edu                if(driving_strength == m_driving_strengths_[i])
8110447Snilay@cs.wisc.edu                {
8210447Snilay@cs.wisc.edu                    is_found = true;
8310447Snilay@cs.wisc.edu                    break;
8410447Snilay@cs.wisc.edu                }
8510447Snilay@cs.wisc.edu            }
8610447Snilay@cs.wisc.edu            ASSERT(is_found, "[Error] " + getInstanceName() +
8710447Snilay@cs.wisc.edu                " -> Driving strength (" + String(driving_strength) + ")"
8810447Snilay@cs.wisc.edu                " not found in available driving strengths (" +
8910447Snilay@cs.wisc.edu                getParameter("AvailableDrivingStrengths"));
9010447Snilay@cs.wisc.edu        }
9110447Snilay@cs.wisc.edu
9210447Snilay@cs.wisc.edu        // Do normal check on the properties
9310447Snilay@cs.wisc.edu        Model::checkProperties();
9410447Snilay@cs.wisc.edu        return;
9510447Snilay@cs.wisc.edu    }
9610447Snilay@cs.wisc.edu
9710447Snilay@cs.wisc.edu    double ElectricalModel::getDrivingStrength() const
9810447Snilay@cs.wisc.edu    {
9910447Snilay@cs.wisc.edu        if(m_curr_driving_strengths_idx_ == -1)
10010447Snilay@cs.wisc.edu        {
10110447Snilay@cs.wisc.edu            return 0;
10210447Snilay@cs.wisc.edu        }
10310447Snilay@cs.wisc.edu        else
10410447Snilay@cs.wisc.edu        {
10510447Snilay@cs.wisc.edu            return m_driving_strengths_[m_curr_driving_strengths_idx_];
10610447Snilay@cs.wisc.edu        }
10710447Snilay@cs.wisc.edu    }
10810447Snilay@cs.wisc.edu
10910447Snilay@cs.wisc.edu    int ElectricalModel::getDrivingStrengthIdx() const
11010447Snilay@cs.wisc.edu    {
11110447Snilay@cs.wisc.edu        return m_curr_driving_strengths_idx_;
11210447Snilay@cs.wisc.edu    }
11310447Snilay@cs.wisc.edu
11410447Snilay@cs.wisc.edu    void ElectricalModel::setDrivingStrengthIdx(int idx_)
11510447Snilay@cs.wisc.edu    {
11610447Snilay@cs.wisc.edu        ASSERT(((idx_ >= 0) && (idx_ < (int)m_driving_strengths_.size())),
11710447Snilay@cs.wisc.edu                "[Error] " + getInstanceName() +
11810447Snilay@cs.wisc.edu                " -> Driving strength index out of range (" + String(idx_) + ")");
11910447Snilay@cs.wisc.edu
12010447Snilay@cs.wisc.edu        m_curr_driving_strengths_idx_ = idx_;
12110447Snilay@cs.wisc.edu        setProperty("DrivingStrength", m_driving_strengths_[m_curr_driving_strengths_idx_]);
12210447Snilay@cs.wisc.edu
12310447Snilay@cs.wisc.edu        Log::printLine(getInstanceName() + " -> Changing drive strength to " + (String) m_driving_strengths_[m_curr_driving_strengths_idx_]);
12410447Snilay@cs.wisc.edu        update();
12510447Snilay@cs.wisc.edu        return;
12610447Snilay@cs.wisc.edu    }
12710447Snilay@cs.wisc.edu
12810447Snilay@cs.wisc.edu    void ElectricalModel::setMinDrivingStrength()
12910447Snilay@cs.wisc.edu    {
13010447Snilay@cs.wisc.edu        setDrivingStrengthIdx(0);
13110447Snilay@cs.wisc.edu        return;
13210447Snilay@cs.wisc.edu    }
13310447Snilay@cs.wisc.edu
13410447Snilay@cs.wisc.edu    bool ElectricalModel::hasMinDrivingStrength() const
13510447Snilay@cs.wisc.edu    {
13610447Snilay@cs.wisc.edu        return (m_curr_driving_strengths_idx_ == 0);
13710447Snilay@cs.wisc.edu    }
13810447Snilay@cs.wisc.edu
13910447Snilay@cs.wisc.edu    bool ElectricalModel::hasMaxDrivingStrength() const
14010447Snilay@cs.wisc.edu    {
14110447Snilay@cs.wisc.edu        return (m_curr_driving_strengths_idx_ == ((int)m_driving_strengths_.size() - 1));
14210447Snilay@cs.wisc.edu    }
14310447Snilay@cs.wisc.edu
14410447Snilay@cs.wisc.edu    void ElectricalModel::increaseDrivingStrength()
14510447Snilay@cs.wisc.edu    {
14610447Snilay@cs.wisc.edu        if(!hasMaxDrivingStrength())
14710447Snilay@cs.wisc.edu        {
14810447Snilay@cs.wisc.edu            setDrivingStrengthIdx(m_curr_driving_strengths_idx_ + 1);
14910447Snilay@cs.wisc.edu        }
15010447Snilay@cs.wisc.edu        return;
15110447Snilay@cs.wisc.edu    }
15210447Snilay@cs.wisc.edu
15310447Snilay@cs.wisc.edu    void ElectricalModel::decreaseDrivingStrength()
15410447Snilay@cs.wisc.edu    {
15510447Snilay@cs.wisc.edu        if(!hasMinDrivingStrength())
15610447Snilay@cs.wisc.edu        {
15710447Snilay@cs.wisc.edu            setDrivingStrengthIdx(m_curr_driving_strengths_idx_ - 1);
15810447Snilay@cs.wisc.edu        }
15910447Snilay@cs.wisc.edu        return;
16010447Snilay@cs.wisc.edu    }
16110447Snilay@cs.wisc.edu
16210447Snilay@cs.wisc.edu    void ElectricalModel::setAvailableDrivingStrengths(const String& driving_strengths_)
16310447Snilay@cs.wisc.edu    {
16410447Snilay@cs.wisc.edu        setParameter("AvailableDrivingStrengths", driving_strengths_);
16510447Snilay@cs.wisc.edu        const vector<String>& split_str = driving_strengths_.split("[,");
16610447Snilay@cs.wisc.edu
16710447Snilay@cs.wisc.edu        // Check if there is at least one driving strength specified
16810447Snilay@cs.wisc.edu        ASSERT(!split_str.empty(), "[Error] " + getInstanceName() +
16910447Snilay@cs.wisc.edu            " -> Specified driving strength string does not contain any driving strengths (" +
17010447Snilay@cs.wisc.edu            driving_strengths_ + ")");
17110447Snilay@cs.wisc.edu
17210447Snilay@cs.wisc.edu        // TODO - check if the driving strengths is sorted
17310447Snilay@cs.wisc.edu
17410447Snilay@cs.wisc.edu        // Overwrite the available driving strengths
17510447Snilay@cs.wisc.edu        m_driving_strengths_.clear();
17610447Snilay@cs.wisc.edu        for(int i = 0; i < (int)split_str.size(); ++i)
17710447Snilay@cs.wisc.edu        {
17810447Snilay@cs.wisc.edu            m_driving_strengths_.push_back(split_str[i].toDouble());
17910447Snilay@cs.wisc.edu        }
18010447Snilay@cs.wisc.edu
18110447Snilay@cs.wisc.edu        // Set the driving strength to minimum
18210447Snilay@cs.wisc.edu        m_curr_driving_strengths_idx_ = 0;
18310447Snilay@cs.wisc.edu        setProperty("DrivingStrength", m_driving_strengths_[m_curr_driving_strengths_idx_]);
18410447Snilay@cs.wisc.edu        return;
18510447Snilay@cs.wisc.edu    }
18610447Snilay@cs.wisc.edu
18710447Snilay@cs.wisc.edu    // Connect a port (input or output) to some ElectricalNet
18810447Snilay@cs.wisc.edu    void ElectricalModel::portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_)
18910447Snilay@cs.wisc.edu    {
19010447Snilay@cs.wisc.edu        ASSERT(m_net_references_->keyExist(connect_net_name_), "[Error] " + getInstanceName() +
19110447Snilay@cs.wisc.edu            " -> Net '" + connect_net_name_ + "' does not exist!");
19210447Snilay@cs.wisc.edu
19310447Snilay@cs.wisc.edu        portConnect(connect_model_, connect_port_name_, connect_net_name_, m_net_references_->get(connect_net_name_));
19410447Snilay@cs.wisc.edu    }
19510447Snilay@cs.wisc.edu
19610447Snilay@cs.wisc.edu    void ElectricalModel::portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_, const NetIndex& connect_net_indices_)
19710447Snilay@cs.wisc.edu    {
19810447Snilay@cs.wisc.edu        ASSERT(m_net_references_->keyExist(connect_net_name_), "[Error] " + getInstanceName() +
19910447Snilay@cs.wisc.edu            " -> Net '" + connect_net_name_ + "' does not exist!");
20010447Snilay@cs.wisc.edu
20110447Snilay@cs.wisc.edu        // Check whether the port name is an input or output, ASSERTion error if neither
20210447Snilay@cs.wisc.edu        bool is_input = connect_model_->getInputs()->keyExist(connect_port_name_);
20310447Snilay@cs.wisc.edu        bool is_output = connect_model_->getOutputs()->keyExist(connect_port_name_);
20410447Snilay@cs.wisc.edu
20510447Snilay@cs.wisc.edu        ASSERT(is_input || is_output, "[Error] " + getInstanceName() + " -> Model '" + connect_model_->getInstanceName() +
20610447Snilay@cs.wisc.edu            "' does not have a port named '" + connect_port_name_ + "'!");
20710447Snilay@cs.wisc.edu
20810447Snilay@cs.wisc.edu        int connect_net_width = connect_net_indices_.second - connect_net_indices_.first + 1;
20910447Snilay@cs.wisc.edu        const NetIndex& port_indices = connect_model_->getNetReference(connect_port_name_);
21010447Snilay@cs.wisc.edu        int port_width = port_indices.second - port_indices.first + 1;
21110447Snilay@cs.wisc.edu
21210447Snilay@cs.wisc.edu        ASSERT(connect_net_width == port_width, "[Error] " + getInstanceName() + " -> Port width mismatch for Model '" +
21310447Snilay@cs.wisc.edu            connect_model_->getInstanceName() + "." + connect_port_name_ + toString(port_indices) +
21410447Snilay@cs.wisc.edu            "' and net '" + connect_net_name_ + toString(connect_net_indices_) + "'!");
21510447Snilay@cs.wisc.edu
21610447Snilay@cs.wisc.edu        int port_index = port_indices.first;
21710447Snilay@cs.wisc.edu        int connect_net_index = connect_net_indices_.first;
21810447Snilay@cs.wisc.edu
21910447Snilay@cs.wisc.edu        if(is_input)
22010447Snilay@cs.wisc.edu        {
22110447Snilay@cs.wisc.edu            while(port_index <= port_indices.second)
22210447Snilay@cs.wisc.edu            {
22310447Snilay@cs.wisc.edu                getNet(connect_net_name_, makeNetIndex(connect_net_index))->addDownstreamNode(
22410447Snilay@cs.wisc.edu                    connect_model_->getNet(connect_port_name_, makeNetIndex(port_index)));
22510447Snilay@cs.wisc.edu                ++port_index;
22610447Snilay@cs.wisc.edu                ++connect_net_index;
22710447Snilay@cs.wisc.edu            }
22810447Snilay@cs.wisc.edu        }
22910447Snilay@cs.wisc.edu        else if(is_output)
23010447Snilay@cs.wisc.edu        {
23110447Snilay@cs.wisc.edu            while (port_index <= port_indices.second)
23210447Snilay@cs.wisc.edu            {
23310447Snilay@cs.wisc.edu                connect_model_->getNet(connect_port_name_, makeNetIndex(port_index))->addDownstreamNode(
23410447Snilay@cs.wisc.edu                    getNet(connect_net_name_, makeNetIndex(connect_net_index)));
23510447Snilay@cs.wisc.edu                ++port_index;
23610447Snilay@cs.wisc.edu                ++connect_net_index;
23710447Snilay@cs.wisc.edu            }
23810447Snilay@cs.wisc.edu        }
23910447Snilay@cs.wisc.edu    }
24010447Snilay@cs.wisc.edu
24110447Snilay@cs.wisc.edu    //Get Drivers
24210447Snilay@cs.wisc.edu    const Map<ElectricalDriver*>* ElectricalModel::getDrivers() const
24310447Snilay@cs.wisc.edu    {
24410447Snilay@cs.wisc.edu        return m_drivers_;
24510447Snilay@cs.wisc.edu    }
24610447Snilay@cs.wisc.edu
24710447Snilay@cs.wisc.edu    ElectricalDriver* ElectricalModel::getDriver(const String& name_)
24810447Snilay@cs.wisc.edu    {
24910447Snilay@cs.wisc.edu        return m_drivers_->get(name_);
25010447Snilay@cs.wisc.edu    }
25110447Snilay@cs.wisc.edu
25210447Snilay@cs.wisc.edu    //Get Driver Multipliers
25310447Snilay@cs.wisc.edu    const Map<ElectricalDriverMultiplier*>* ElectricalModel::getDriverMultipliers() const
25410447Snilay@cs.wisc.edu    {
25510447Snilay@cs.wisc.edu        return m_driver_multipliers_;
25610447Snilay@cs.wisc.edu    }
25710447Snilay@cs.wisc.edu
25810447Snilay@cs.wisc.edu    ElectricalDriverMultiplier* ElectricalModel::getDriverMultiplier(const String& name_)
25910447Snilay@cs.wisc.edu    {
26010447Snilay@cs.wisc.edu        return m_driver_multipliers_->get(name_);
26110447Snilay@cs.wisc.edu    }
26210447Snilay@cs.wisc.edu
26310447Snilay@cs.wisc.edu    //Get Nets
26410447Snilay@cs.wisc.edu    const Map<ElectricalNet*>* ElectricalModel::getNets() const
26510447Snilay@cs.wisc.edu    {
26610447Snilay@cs.wisc.edu        return m_nets_;
26710447Snilay@cs.wisc.edu    }
26810447Snilay@cs.wisc.edu
26910447Snilay@cs.wisc.edu    ElectricalNet* ElectricalModel::getNet(const String& name_)
27010447Snilay@cs.wisc.edu    {
27110447Snilay@cs.wisc.edu        return getNet(name_, m_net_references_->get(name_));
27210447Snilay@cs.wisc.edu    }
27310447Snilay@cs.wisc.edu
27410447Snilay@cs.wisc.edu    ElectricalNet* ElectricalModel::getNet(const String& name_, const NetIndex& index_)
27510447Snilay@cs.wisc.edu    {
27610447Snilay@cs.wisc.edu        ASSERT(index_.first == index_.second, "[Error] " + getInstanceName() +
27710447Snilay@cs.wisc.edu            " -> Ambiguous get net since (" + name_ + ") is a bus consisting of several nets!");
27810447Snilay@cs.wisc.edu        return m_nets_->get(name_ + "[" + (String) index_.first + "]");
27910447Snilay@cs.wisc.edu    }
28010447Snilay@cs.wisc.edu
28110447Snilay@cs.wisc.edu    //Get Loads
28210447Snilay@cs.wisc.edu    const Map<ElectricalLoad*>* ElectricalModel::getLoads() const
28310447Snilay@cs.wisc.edu    {
28410447Snilay@cs.wisc.edu        return m_loads_;
28510447Snilay@cs.wisc.edu    }
28610447Snilay@cs.wisc.edu
28710447Snilay@cs.wisc.edu    ElectricalLoad* ElectricalModel::getLoad(const String& name_)
28810447Snilay@cs.wisc.edu    {
28910447Snilay@cs.wisc.edu        return m_loads_->get(name_);
29010447Snilay@cs.wisc.edu    }
29110447Snilay@cs.wisc.edu
29210447Snilay@cs.wisc.edu    //Get Delays
29310447Snilay@cs.wisc.edu    const Map<ElectricalDelay*>* ElectricalModel::getDelays() const
29410447Snilay@cs.wisc.edu    {
29510447Snilay@cs.wisc.edu        return m_delays_;
29610447Snilay@cs.wisc.edu    }
29710447Snilay@cs.wisc.edu
29810447Snilay@cs.wisc.edu    ElectricalDelay* ElectricalModel::getDelay(const String& name_)
29910447Snilay@cs.wisc.edu    {
30010447Snilay@cs.wisc.edu        return m_delays_->get(name_);
30110447Snilay@cs.wisc.edu    }
30210447Snilay@cs.wisc.edu
30310447Snilay@cs.wisc.edu    //Get Inputs
30410447Snilay@cs.wisc.edu    const Map<PortInfo*>* ElectricalModel::getInputs() const
30510447Snilay@cs.wisc.edu    {
30610447Snilay@cs.wisc.edu        return m_input_ports_;
30710447Snilay@cs.wisc.edu    }
30810447Snilay@cs.wisc.edu
30910447Snilay@cs.wisc.edu    PortInfo* ElectricalModel::getInputPort(const String& name_)
31010447Snilay@cs.wisc.edu    {
31110447Snilay@cs.wisc.edu        ASSERT(m_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
31210447Snilay@cs.wisc.edu                " -> Input port (" + name_ + ") does not exist");
31310447Snilay@cs.wisc.edu
31410447Snilay@cs.wisc.edu        return m_input_ports_->get(name_);
31510447Snilay@cs.wisc.edu    }
31610447Snilay@cs.wisc.edu
31710447Snilay@cs.wisc.edu    const PortInfo* ElectricalModel::getInputPort(const String& name_) const
31810447Snilay@cs.wisc.edu    {
31910447Snilay@cs.wisc.edu        ASSERT(m_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
32010447Snilay@cs.wisc.edu                " -> Input port (" + name_ + ") does not exist");
32110447Snilay@cs.wisc.edu
32210447Snilay@cs.wisc.edu        return m_input_ports_->get(name_);
32310447Snilay@cs.wisc.edu    }
32410447Snilay@cs.wisc.edu
32510447Snilay@cs.wisc.edu    //Get Outputs
32610447Snilay@cs.wisc.edu    const Map<PortInfo*>* ElectricalModel::getOutputs() const
32710447Snilay@cs.wisc.edu    {
32810447Snilay@cs.wisc.edu        return m_output_ports_;
32910447Snilay@cs.wisc.edu    }
33010447Snilay@cs.wisc.edu
33110447Snilay@cs.wisc.edu    PortInfo* ElectricalModel::getOutputPort(const String& name_)
33210447Snilay@cs.wisc.edu    {
33310447Snilay@cs.wisc.edu        ASSERT(m_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
33410447Snilay@cs.wisc.edu                " -> Output port (" + name_ + ") does not exist");
33510447Snilay@cs.wisc.edu
33610447Snilay@cs.wisc.edu        return m_output_ports_->get(name_);
33710447Snilay@cs.wisc.edu    }
33810447Snilay@cs.wisc.edu
33910447Snilay@cs.wisc.edu    const PortInfo* ElectricalModel::getOutputPort(const String& name_) const
34010447Snilay@cs.wisc.edu    {
34110447Snilay@cs.wisc.edu        ASSERT(m_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
34210447Snilay@cs.wisc.edu                " -> Output port (" + name_ + ") does not exist");
34310447Snilay@cs.wisc.edu
34410447Snilay@cs.wisc.edu        return m_output_ports_->get(name_);
34510447Snilay@cs.wisc.edu    }
34610447Snilay@cs.wisc.edu
34710447Snilay@cs.wisc.edu    const Map<NetIndex>* ElectricalModel::getNetReferences() const
34810447Snilay@cs.wisc.edu    {
34910447Snilay@cs.wisc.edu        return m_net_references_;
35010447Snilay@cs.wisc.edu    }
35110447Snilay@cs.wisc.edu
35210447Snilay@cs.wisc.edu    const NetIndex ElectricalModel::getNetReference(const String& name_) const
35310447Snilay@cs.wisc.edu    {
35410447Snilay@cs.wisc.edu        return m_net_references_->get(name_);
35510447Snilay@cs.wisc.edu    }
35610447Snilay@cs.wisc.edu
35710447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
35810447Snilay@cs.wisc.edu    //  Electrical Connectivity and Timing Element Creation Functions
35910447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
36010447Snilay@cs.wisc.edu
36110447Snilay@cs.wisc.edu    // Input Port creation
36210447Snilay@cs.wisc.edu    void ElectricalModel::createInputPort(const String& name_, const NetIndex& net_indices_)
36310447Snilay@cs.wisc.edu    {
36410447Snilay@cs.wisc.edu        // Create the new nets (including its net reference)
36510447Snilay@cs.wisc.edu        // This should already check that it has not been previously declared
36610447Snilay@cs.wisc.edu        createNet(name_, net_indices_);
36710447Snilay@cs.wisc.edu        // Add the net name to list of input ports
36810447Snilay@cs.wisc.edu        m_input_ports_->set(name_, new PortInfo(name_, net_indices_));
36910447Snilay@cs.wisc.edu        return;
37010447Snilay@cs.wisc.edu    }
37110447Snilay@cs.wisc.edu
37210447Snilay@cs.wisc.edu    // Output Port creation
37310447Snilay@cs.wisc.edu    void ElectricalModel::createOutputPort(const String& name_, const NetIndex& net_indices_)
37410447Snilay@cs.wisc.edu    {
37510447Snilay@cs.wisc.edu        // Create the new nets (including its net reference)
37610447Snilay@cs.wisc.edu        // This should already check that it has not been previously declared
37710447Snilay@cs.wisc.edu        createNet(name_, net_indices_);
37810447Snilay@cs.wisc.edu        // Add the net name to list of output ports
37910447Snilay@cs.wisc.edu        m_output_ports_->set(name_, new PortInfo(name_, net_indices_));
38010447Snilay@cs.wisc.edu        return;
38110447Snilay@cs.wisc.edu    }
38210447Snilay@cs.wisc.edu
38310447Snilay@cs.wisc.edu    // Net creation
38410447Snilay@cs.wisc.edu    void ElectricalModel::createNet(const String& name_)
38510447Snilay@cs.wisc.edu    {
38610447Snilay@cs.wisc.edu        // Creating a net with specifying an index range means that the net is just
38710447Snilay@cs.wisc.edu        // a 1-bit wire indexed at [0]
38810447Snilay@cs.wisc.edu        createNet(name_, makeNetIndex(0, 0));
38910447Snilay@cs.wisc.edu        return;
39010447Snilay@cs.wisc.edu    }
39110447Snilay@cs.wisc.edu
39210447Snilay@cs.wisc.edu    void ElectricalModel::createNet(const String& name_, const NetIndex& net_indices_)
39310447Snilay@cs.wisc.edu    {
39410447Snilay@cs.wisc.edu        // Check that it hasn't been previously declared
39510447Snilay@cs.wisc.edu        ASSERT( !m_nets_->keyExist(name_) && !m_net_references_->keyExist(name_),
39610447Snilay@cs.wisc.edu                "[Error] " + getInstanceName() + " -> Redeclaration of net " + name_);
39710447Snilay@cs.wisc.edu
39810447Snilay@cs.wisc.edu        int start = net_indices_.first;
39910447Snilay@cs.wisc.edu        int end = net_indices_.second;
40010447Snilay@cs.wisc.edu
40110447Snilay@cs.wisc.edu        for (int index = start; index <= end; ++index)
40210447Snilay@cs.wisc.edu        {
40310447Snilay@cs.wisc.edu            String indexed_name = name_ + "[" + (String) index + "]";
40410447Snilay@cs.wisc.edu            // Create the new net
40510447Snilay@cs.wisc.edu            ElectricalNet* net = new ElectricalNet(indexed_name, this);
40610447Snilay@cs.wisc.edu            // Add the net to net map
40710447Snilay@cs.wisc.edu            m_nets_->set(indexed_name, net);
40810447Snilay@cs.wisc.edu        }
40910447Snilay@cs.wisc.edu        // Add net to net references
41010447Snilay@cs.wisc.edu        m_net_references_->set(name_, net_indices_);
41110447Snilay@cs.wisc.edu        return;
41210447Snilay@cs.wisc.edu    }
41310447Snilay@cs.wisc.edu
41410447Snilay@cs.wisc.edu    // Driver creation
41510447Snilay@cs.wisc.edu    void ElectricalModel::createDriver(const String& name_, bool sizable_)
41610447Snilay@cs.wisc.edu    {
41710447Snilay@cs.wisc.edu        // Check that it hasn't been previously declared
41810447Snilay@cs.wisc.edu        ASSERT( !m_drivers_->keyExist(name_),
41910447Snilay@cs.wisc.edu                "[Error] " + getInstanceName() + " -> Redeclaration of driver " + name_);
42010447Snilay@cs.wisc.edu
42110447Snilay@cs.wisc.edu        ElectricalDriver* driver = new ElectricalDriver(name_, this, sizable_);
42210447Snilay@cs.wisc.edu        m_drivers_->set(name_, driver);
42310447Snilay@cs.wisc.edu        return;
42410447Snilay@cs.wisc.edu    }
42510447Snilay@cs.wisc.edu
42610447Snilay@cs.wisc.edu    /*
42710447Snilay@cs.wisc.edu    void ElectricalModel::createDriver(const String& name_, bool sizable_, int start_index_, int end_index_)
42810447Snilay@cs.wisc.edu    {
42910447Snilay@cs.wisc.edu        for (int index = start_index_; index <= end_index_; ++index)
43010447Snilay@cs.wisc.edu        {
43110447Snilay@cs.wisc.edu            createDriver(name_ + "[" + (String) index + "]", sizable_);
43210447Snilay@cs.wisc.edu        }
43310447Snilay@cs.wisc.edu        return;
43410447Snilay@cs.wisc.edu    }
43510447Snilay@cs.wisc.edu    */
43610447Snilay@cs.wisc.edu
43710447Snilay@cs.wisc.edu    // Driver Multiplier creation
43810447Snilay@cs.wisc.edu    void ElectricalModel::createDriverMultiplier(const String& name_)
43910447Snilay@cs.wisc.edu    {
44010447Snilay@cs.wisc.edu        // Check that it hasn't been previously declared
44110447Snilay@cs.wisc.edu        ASSERT( !m_driver_multipliers_->keyExist(name_),
44210447Snilay@cs.wisc.edu                "[Error] " + getInstanceName() + " -> Redeclaration of driver_multiplier " + name_);
44310447Snilay@cs.wisc.edu
44410447Snilay@cs.wisc.edu        ElectricalDriverMultiplier* driver_multiplier = new ElectricalDriverMultiplier(name_, this);
44510447Snilay@cs.wisc.edu        m_driver_multipliers_->set(name_, driver_multiplier);
44610447Snilay@cs.wisc.edu        return;
44710447Snilay@cs.wisc.edu    }
44810447Snilay@cs.wisc.edu
44910447Snilay@cs.wisc.edu    // Load creation
45010447Snilay@cs.wisc.edu
45110447Snilay@cs.wisc.edu    void ElectricalModel::createLoad(const String& name_)
45210447Snilay@cs.wisc.edu    {
45310447Snilay@cs.wisc.edu        // Check that it hasn't been previously declared
45410447Snilay@cs.wisc.edu        ASSERT( !m_loads_->keyExist(name_),
45510447Snilay@cs.wisc.edu                "[Error] " + getInstanceName() + " -> Redeclaration of load " + name_);
45610447Snilay@cs.wisc.edu
45710447Snilay@cs.wisc.edu        ElectricalLoad* load = new ElectricalLoad(name_, this);
45810447Snilay@cs.wisc.edu        m_loads_->set(name_, load);
45910447Snilay@cs.wisc.edu        return;
46010447Snilay@cs.wisc.edu    }
46110447Snilay@cs.wisc.edu
46210447Snilay@cs.wisc.edu    /*
46310447Snilay@cs.wisc.edu    void ElectricalModel::createLoad(const String& name_, int start_index_, int end_index_)
46410447Snilay@cs.wisc.edu    {
46510447Snilay@cs.wisc.edu        for (int index = start_index_; index <= end_index_; ++index)
46610447Snilay@cs.wisc.edu        {
46710447Snilay@cs.wisc.edu            createLoad(name_ + "[" + (String) index + "]");
46810447Snilay@cs.wisc.edu        }
46910447Snilay@cs.wisc.edu        return;
47010447Snilay@cs.wisc.edu    }
47110447Snilay@cs.wisc.edu    */
47210447Snilay@cs.wisc.edu
47310447Snilay@cs.wisc.edu    // Delay creation
47410447Snilay@cs.wisc.edu    void ElectricalModel::createDelay(const String& name_)
47510447Snilay@cs.wisc.edu    {
47610447Snilay@cs.wisc.edu        // Check that it hasn't been previously declared
47710447Snilay@cs.wisc.edu        ASSERT( !m_delays_->keyExist(name_),
47810447Snilay@cs.wisc.edu                "[Error] " + getInstanceName() + " -> Redeclaration of delay " + name_);
47910447Snilay@cs.wisc.edu
48010447Snilay@cs.wisc.edu        ElectricalDelay* delay = new ElectricalDelay(name_, this);
48110447Snilay@cs.wisc.edu        m_delays_->set(name_, delay);
48210447Snilay@cs.wisc.edu        return;
48310447Snilay@cs.wisc.edu    }
48410447Snilay@cs.wisc.edu
48510447Snilay@cs.wisc.edu    /*
48610447Snilay@cs.wisc.edu    void ElectricalModel::createDelay(const String& name_, int start_index_, int end_index_)
48710447Snilay@cs.wisc.edu    {
48810447Snilay@cs.wisc.edu        for (int index = start_index_; index <= end_index_; ++index)
48910447Snilay@cs.wisc.edu        {
49010447Snilay@cs.wisc.edu            createDelay(name_ + "[" + (String) index + "]");
49110447Snilay@cs.wisc.edu        }
49210447Snilay@cs.wisc.edu        return;
49310447Snilay@cs.wisc.edu    }
49410447Snilay@cs.wisc.edu    */
49510447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
49610447Snilay@cs.wisc.edu
49710447Snilay@cs.wisc.edu    // Assign a net to be downstream from another net
49810447Snilay@cs.wisc.edu    // case 1: 'assign downstream_net_name_ = upstream_net_name_'
49910447Snilay@cs.wisc.edu    void ElectricalModel::assign(const String& downstream_net_name_, const String& upstream_net_name_)
50010447Snilay@cs.wisc.edu    {
50110447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
50210447Snilay@cs.wisc.edu            downstream_net_name_ + "' does not exist!");
50310447Snilay@cs.wisc.edu
50410447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
50510447Snilay@cs.wisc.edu            upstream_net_name_ + "' does not exist!");
50610447Snilay@cs.wisc.edu
50710447Snilay@cs.wisc.edu        assign(downstream_net_name_, getNetReference(downstream_net_name_),
50810447Snilay@cs.wisc.edu            upstream_net_name_, getNetReference(upstream_net_name_));
50910447Snilay@cs.wisc.edu
51010447Snilay@cs.wisc.edu        return;
51110447Snilay@cs.wisc.edu    }
51210447Snilay@cs.wisc.edu
51310447Snilay@cs.wisc.edu    // case 2: 'assign downstream_net_name_[begin:end] = upstream_net_name_'
51410447Snilay@cs.wisc.edu    void ElectricalModel::assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_)
51510447Snilay@cs.wisc.edu    {
51610447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
51710447Snilay@cs.wisc.edu            downstream_net_name_ + "' does not exist!");
51810447Snilay@cs.wisc.edu
51910447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
52010447Snilay@cs.wisc.edu            upstream_net_name_ + "' does not exist!");
52110447Snilay@cs.wisc.edu
52210447Snilay@cs.wisc.edu        assign(downstream_net_name_, downstream_net_indices_,
52310447Snilay@cs.wisc.edu            upstream_net_name_, getNetReference(upstream_net_name_));
52410447Snilay@cs.wisc.edu
52510447Snilay@cs.wisc.edu        return;
52610447Snilay@cs.wisc.edu    }
52710447Snilay@cs.wisc.edu
52810447Snilay@cs.wisc.edu    // case 3: 'assign downstream_net_name_ = upstream_net_name_[begin:end]'
52910447Snilay@cs.wisc.edu    void ElectricalModel::assign(const String& downstream_net_name_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
53010447Snilay@cs.wisc.edu    {
53110447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
53210447Snilay@cs.wisc.edu            downstream_net_name_ + "' does not exist!");
53310447Snilay@cs.wisc.edu
53410447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
53510447Snilay@cs.wisc.edu            upstream_net_name_ + "' does not exist!");
53610447Snilay@cs.wisc.edu
53710447Snilay@cs.wisc.edu        assign(downstream_net_name_, getNetReference(downstream_net_name_),
53810447Snilay@cs.wisc.edu            upstream_net_name_, upstream_net_indices_);
53910447Snilay@cs.wisc.edu
54010447Snilay@cs.wisc.edu        return;
54110447Snilay@cs.wisc.edu    }
54210447Snilay@cs.wisc.edu    // case 4: 'assign downstream_net_name_[begin:end] = upstream_net_name_[begin:end]'
54310447Snilay@cs.wisc.edu    void ElectricalModel::assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
54410447Snilay@cs.wisc.edu    {
54510447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
54610447Snilay@cs.wisc.edu            downstream_net_name_ + "' does not exist!");
54710447Snilay@cs.wisc.edu
54810447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
54910447Snilay@cs.wisc.edu            upstream_net_name_ + "' does not exist!");
55010447Snilay@cs.wisc.edu
55110447Snilay@cs.wisc.edu        // Check that the assignment widths are the same
55210447Snilay@cs.wisc.edu        int downstream_width = downstream_net_indices_.second - downstream_net_indices_.first + 1;
55310447Snilay@cs.wisc.edu        int upstream_width = upstream_net_indices_.second - upstream_net_indices_.first + 1;
55410447Snilay@cs.wisc.edu
55510447Snilay@cs.wisc.edu        ASSERT(downstream_width == upstream_width, "[Error] " + getInstanceName() + " -> Assignment width mismatch: " +
55610447Snilay@cs.wisc.edu            downstream_net_name_ + " (" + (String) downstream_width + ") and " +
55710447Snilay@cs.wisc.edu            upstream_net_name_ + " (" + (String) upstream_width + ")");
55810447Snilay@cs.wisc.edu
55910447Snilay@cs.wisc.edu        // Loop through indices and connect them together
56010447Snilay@cs.wisc.edu        int down_index = downstream_net_indices_.first;
56110447Snilay@cs.wisc.edu        int up_index = upstream_net_indices_.first;
56210447Snilay@cs.wisc.edu        while (down_index <= downstream_net_indices_.second)
56310447Snilay@cs.wisc.edu        {
56410447Snilay@cs.wisc.edu            getNet(upstream_net_name_, makeNetIndex(up_index))->addDownstreamNode(
56510447Snilay@cs.wisc.edu                getNet(downstream_net_name_, makeNetIndex(down_index)));
56610447Snilay@cs.wisc.edu
56710447Snilay@cs.wisc.edu            ++up_index;
56810447Snilay@cs.wisc.edu            ++down_index;
56910447Snilay@cs.wisc.edu        }
57010447Snilay@cs.wisc.edu
57110447Snilay@cs.wisc.edu        return;
57210447Snilay@cs.wisc.edu    }
57310447Snilay@cs.wisc.edu
57410447Snilay@cs.wisc.edu    // Assign a net to another net through a driver multiplier
57510447Snilay@cs.wisc.edu    void ElectricalModel::assignVirtualFanout(const String& downstream_net_name_, const String& upstream_net_name_)
57610447Snilay@cs.wisc.edu    {
57710447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
57810447Snilay@cs.wisc.edu                " -> Net '" + upstream_net_name_ + "' does not exist!");
57910447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
58010447Snilay@cs.wisc.edu                " -> Net '" + downstream_net_name_ + "' does not exist!");
58110447Snilay@cs.wisc.edu
58210447Snilay@cs.wisc.edu        assignVirtualFanout(downstream_net_name_, getNetReference(downstream_net_name_), upstream_net_name_, getNetReference(upstream_net_name_));
58310447Snilay@cs.wisc.edu        return;
58410447Snilay@cs.wisc.edu    }
58510447Snilay@cs.wisc.edu
58610447Snilay@cs.wisc.edu    // Assign a net to another net through a driver multiplier
58710447Snilay@cs.wisc.edu    void ElectricalModel::assignVirtualFanout(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
58810447Snilay@cs.wisc.edu    {
58910447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
59010447Snilay@cs.wisc.edu                " -> Net '" + upstream_net_name_ + "' does not exist!");
59110447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
59210447Snilay@cs.wisc.edu                " -> Net '" + downstream_net_name_ + "' does not exist!");
59310447Snilay@cs.wisc.edu
59410447Snilay@cs.wisc.edu        const String& drive_mult_name = upstream_net_name_ + "_" + (String) upstream_net_indices_.first + "_DriverMultiplier";
59510447Snilay@cs.wisc.edu        bool is_drive_mult_exist = getDriverMultipliers()->keyExist(drive_mult_name);
59610447Snilay@cs.wisc.edu
59710447Snilay@cs.wisc.edu        // Create a driver multiplier and assign it to upstream_net since it doesn't exist
59810447Snilay@cs.wisc.edu        if(!is_drive_mult_exist)
59910447Snilay@cs.wisc.edu        {
60010447Snilay@cs.wisc.edu            createDriverMultiplier(drive_mult_name);
60110447Snilay@cs.wisc.edu            getNet(upstream_net_name_, upstream_net_indices_)->addDownstreamNode(getDriverMultiplier(drive_mult_name));
60210447Snilay@cs.wisc.edu        }
60310447Snilay@cs.wisc.edu
60410447Snilay@cs.wisc.edu        // Assign downstream_net_name_[end:begin] = driver_multiplier_name_
60510447Snilay@cs.wisc.edu        ElectricalDriverMultiplier* drive_mult = getDriverMultiplier(drive_mult_name);
60610447Snilay@cs.wisc.edu        int begin_index = downstream_net_indices_.first;
60710447Snilay@cs.wisc.edu        int end_index = downstream_net_indices_.second;
60810447Snilay@cs.wisc.edu        for(int i = begin_index; i <= end_index; ++i)
60910447Snilay@cs.wisc.edu        {
61010447Snilay@cs.wisc.edu            drive_mult->addDownstreamNode(getNet(downstream_net_name_, makeNetIndex(i)));
61110447Snilay@cs.wisc.edu        }
61210447Snilay@cs.wisc.edu        return;
61310447Snilay@cs.wisc.edu    }
61410447Snilay@cs.wisc.edu
61510447Snilay@cs.wisc.edu    void ElectricalModel::assignVirtualFanin(const String& downstream_net_name_, const String& upstream_net_name_)
61610447Snilay@cs.wisc.edu    {
61710447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
61810447Snilay@cs.wisc.edu                " -> Net '" + upstream_net_name_ + "' does not exist!");
61910447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
62010447Snilay@cs.wisc.edu                " -> Net '" + downstream_net_name_ + "' does not exist!");
62110447Snilay@cs.wisc.edu
62210447Snilay@cs.wisc.edu        assignVirtualFanin(downstream_net_name_, getNetReference(downstream_net_name_), upstream_net_name_, getNetReference(upstream_net_name_));
62310447Snilay@cs.wisc.edu        return;
62410447Snilay@cs.wisc.edu    }
62510447Snilay@cs.wisc.edu
62610447Snilay@cs.wisc.edu    void ElectricalModel::assignVirtualFanin(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
62710447Snilay@cs.wisc.edu    {
62810447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
62910447Snilay@cs.wisc.edu                " -> Net '" + upstream_net_name_ + "' does not exist!");
63010447Snilay@cs.wisc.edu        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
63110447Snilay@cs.wisc.edu                " -> Net '" + downstream_net_name_ + "' does not exist!");
63210447Snilay@cs.wisc.edu
63310447Snilay@cs.wisc.edu        int begin_index = upstream_net_indices_.first;
63410447Snilay@cs.wisc.edu        int end_index = upstream_net_indices_.second;
63510447Snilay@cs.wisc.edu
63610447Snilay@cs.wisc.edu        for(int i = begin_index; i <= end_index; ++i)
63710447Snilay@cs.wisc.edu        {
63810447Snilay@cs.wisc.edu            getNet(upstream_net_name_, makeNetIndex(i))->addDownstreamNode(getNet(downstream_net_name_, downstream_net_indices_));
63910447Snilay@cs.wisc.edu        }
64010447Snilay@cs.wisc.edu        return;
64110447Snilay@cs.wisc.edu    }
64210447Snilay@cs.wisc.edu
64310447Snilay@cs.wisc.edu    void ElectricalModel::createElectricalResults()
64410447Snilay@cs.wisc.edu    {
64510447Snilay@cs.wisc.edu        // Add active area result
64610447Snilay@cs.wisc.edu        addAreaResult(new Result("Active"));
64710447Snilay@cs.wisc.edu
64810447Snilay@cs.wisc.edu        // Add wire area result
64910447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
65010447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
65110447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it;
65210447Snilay@cs.wisc.edu        for(it = it_begin; it != it_end; ++it)
65310447Snilay@cs.wisc.edu        {
65410447Snilay@cs.wisc.edu            const String& layer_name = (*it);
65510447Snilay@cs.wisc.edu            addAreaResult(new Result(layer_name + "Wire"));
65610447Snilay@cs.wisc.edu        }
65710447Snilay@cs.wisc.edu
65810447Snilay@cs.wisc.edu        // Add leakage result
65910447Snilay@cs.wisc.edu        addNddPowerResult(new Result("Leakage"));
66010447Snilay@cs.wisc.edu
66110447Snilay@cs.wisc.edu        // Add idle event result
66210447Snilay@cs.wisc.edu        createElectricalEventResult("Idle");
66310447Snilay@cs.wisc.edu        return;
66410447Snilay@cs.wisc.edu    }
66510447Snilay@cs.wisc.edu
66610447Snilay@cs.wisc.edu    void ElectricalModel::addElectricalSubResults(const ElectricalModel* model_, double number_models_)
66710447Snilay@cs.wisc.edu    {
66810447Snilay@cs.wisc.edu        // Add active area sub result
66910447Snilay@cs.wisc.edu        getAreaResult("Active")->addSubResult(model_->getAreaResult("Active"), model_->getInstanceName(), number_models_);
67010447Snilay@cs.wisc.edu
67110447Snilay@cs.wisc.edu        // Add wire area sub result
67210447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
67310447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
67410447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it;
67510447Snilay@cs.wisc.edu        for(it = it_begin; it != it_end; ++it)
67610447Snilay@cs.wisc.edu        {
67710447Snilay@cs.wisc.edu            const String& layer_name = (*it);
67810447Snilay@cs.wisc.edu            const String& result_name = layer_name + "Wire";
67910447Snilay@cs.wisc.edu            getAreaResult(result_name)->addSubResult(model_->getAreaResult(result_name), model_->getInstanceName(), number_models_);
68010447Snilay@cs.wisc.edu        }
68110447Snilay@cs.wisc.edu
68210447Snilay@cs.wisc.edu        // Add leakage sub result
68310447Snilay@cs.wisc.edu        getNddPowerResult("Leakage")->addSubResult(model_->getNddPowerResult("Leakage"), model_->getInstanceName(), number_models_);
68410447Snilay@cs.wisc.edu
68510447Snilay@cs.wisc.edu        // Add idle event sub result
68610447Snilay@cs.wisc.edu        getEventResult("Idle")->addSubResult(model_->getEventResult("Idle"), model_->getInstanceName(), number_models_);
68710447Snilay@cs.wisc.edu        return;
68810447Snilay@cs.wisc.edu    }
68910447Snilay@cs.wisc.edu
69010447Snilay@cs.wisc.edu    void ElectricalModel::addElectricalWireSubResult(const String& wire_layer_, const Result* result_, const String& producer_, double number_results_)
69110447Snilay@cs.wisc.edu    {
69210447Snilay@cs.wisc.edu        getAreaResult(wire_layer_ + "Wire")->addSubResult(result_, producer_, number_results_);
69310447Snilay@cs.wisc.edu        return;
69410447Snilay@cs.wisc.edu    }
69510447Snilay@cs.wisc.edu
69610447Snilay@cs.wisc.edu    void ElectricalModel::createElectricalAtomicResults()
69710447Snilay@cs.wisc.edu    {
69810447Snilay@cs.wisc.edu        // Add active area result
69910447Snilay@cs.wisc.edu        addAreaResult(new AtomicResult("Active"));
70010447Snilay@cs.wisc.edu
70110447Snilay@cs.wisc.edu        // Add wire area result
70210447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
70310447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
70410447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it;
70510447Snilay@cs.wisc.edu        for(it = it_begin; it != it_end; ++it)
70610447Snilay@cs.wisc.edu        {
70710447Snilay@cs.wisc.edu            const String& layer_name = (*it);
70810447Snilay@cs.wisc.edu            addAreaResult(new AtomicResult(layer_name + "Wire"));
70910447Snilay@cs.wisc.edu        }
71010447Snilay@cs.wisc.edu
71110447Snilay@cs.wisc.edu        // Add leakage result
71210447Snilay@cs.wisc.edu        addNddPowerResult(new AtomicResult("Leakage"));
71310447Snilay@cs.wisc.edu
71410447Snilay@cs.wisc.edu        // Add idle event result
71510447Snilay@cs.wisc.edu        createElectricalEventAtomicResult("Idle");
71610447Snilay@cs.wisc.edu        return;
71710447Snilay@cs.wisc.edu    }
71810447Snilay@cs.wisc.edu
71910447Snilay@cs.wisc.edu    void ElectricalModel::addElecticalAtomicResultValues(const ElectricalModel* model_, double number_models_)
72010447Snilay@cs.wisc.edu    {
72110447Snilay@cs.wisc.edu        getAreaResult("Active")->addValue(model_->getAreaResult("Active")->calculateSum() * number_models_);
72210447Snilay@cs.wisc.edu
72310447Snilay@cs.wisc.edu        // Add wire area sub result
72410447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
72510447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
72610447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it;
72710447Snilay@cs.wisc.edu        for(it = it_begin; it != it_end; ++it)
72810447Snilay@cs.wisc.edu        {
72910447Snilay@cs.wisc.edu            const String& layer_name = (*it);
73010447Snilay@cs.wisc.edu            const String& result_name = layer_name + "Wire";
73110447Snilay@cs.wisc.edu            getAreaResult(result_name)->addValue(model_->getAreaResult(result_name)->calculateSum() * number_models_);
73210447Snilay@cs.wisc.edu        }
73310447Snilay@cs.wisc.edu
73410447Snilay@cs.wisc.edu        // Add leakage sub result
73510447Snilay@cs.wisc.edu        getNddPowerResult("Leakage")->addValue(model_->getNddPowerResult("Leakage")->calculateSum() * number_models_);
73610447Snilay@cs.wisc.edu
73710447Snilay@cs.wisc.edu        // Add idle event sub result
73810447Snilay@cs.wisc.edu        getEventResult("Idle")->addValue(model_->getEventResult("Idle")->calculateSum() * number_models_);
73910447Snilay@cs.wisc.edu        return;
74010447Snilay@cs.wisc.edu    }
74110447Snilay@cs.wisc.edu
74210447Snilay@cs.wisc.edu    void ElectricalModel::addElecticalWireAtomicResultValue(const String& wire_layer_, double value_)
74310447Snilay@cs.wisc.edu    {
74410447Snilay@cs.wisc.edu        getAreaResult(wire_layer_ + "Wire")->addValue(value_);
74510447Snilay@cs.wisc.edu        return;
74610447Snilay@cs.wisc.edu    }
74710447Snilay@cs.wisc.edu
74810447Snilay@cs.wisc.edu    void ElectricalModel::resetElectricalAtomicResults()
74910447Snilay@cs.wisc.edu    {
75010447Snilay@cs.wisc.edu        getAreaResult("Active")->setValue(0.0);
75110447Snilay@cs.wisc.edu
75210447Snilay@cs.wisc.edu        // Reset wire area sub result
75310447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
75410447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
75510447Snilay@cs.wisc.edu        TechModel::ConstWireLayerIterator it;
75610447Snilay@cs.wisc.edu        for(it = it_begin; it != it_end; ++it)
75710447Snilay@cs.wisc.edu        {
75810447Snilay@cs.wisc.edu            const String& layer_name = (*it);
75910447Snilay@cs.wisc.edu            const String& result_name = layer_name + "Wire";
76010447Snilay@cs.wisc.edu            getAreaResult(result_name)->setValue(0.0);
76110447Snilay@cs.wisc.edu        }
76210447Snilay@cs.wisc.edu
76310447Snilay@cs.wisc.edu        // Reset leakage sub result
76410447Snilay@cs.wisc.edu        getNddPowerResult("Leakage")->setValue(0.0);
76510447Snilay@cs.wisc.edu
76610447Snilay@cs.wisc.edu        // Reset idle event sub result
76710447Snilay@cs.wisc.edu        getEventResult("Idle")->setValue(0.0);
76810447Snilay@cs.wisc.edu
76910447Snilay@cs.wisc.edu        return;
77010447Snilay@cs.wisc.edu    }
77110447Snilay@cs.wisc.edu
77210447Snilay@cs.wisc.edu    void ElectricalModel::createElectricalEventResult(const String& name_)
77310447Snilay@cs.wisc.edu    {
77410447Snilay@cs.wisc.edu        // Add the event result
77510447Snilay@cs.wisc.edu        addEventResult(new Result(name_));
77610447Snilay@cs.wisc.edu        // Add event info
77710447Snilay@cs.wisc.edu        m_event_infos_->set(name_, new EventInfo(name_, getInputs()));
77810447Snilay@cs.wisc.edu        return;
77910447Snilay@cs.wisc.edu    }
78010447Snilay@cs.wisc.edu
78110447Snilay@cs.wisc.edu    void ElectricalModel::createElectricalEventAtomicResult(const String& name_)
78210447Snilay@cs.wisc.edu    {
78310447Snilay@cs.wisc.edu        // Add the event result
78410447Snilay@cs.wisc.edu        addEventResult(new AtomicResult(name_));
78510447Snilay@cs.wisc.edu        // Add event info
78610447Snilay@cs.wisc.edu        m_event_infos_->set(name_, new EventInfo(name_, getInputs()));
78710447Snilay@cs.wisc.edu        return;
78810447Snilay@cs.wisc.edu    }
78910447Snilay@cs.wisc.edu
79010447Snilay@cs.wisc.edu    void ElectricalModel::assignPortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const TransitionInfo& trans_info_)
79110447Snilay@cs.wisc.edu    {
79210447Snilay@cs.wisc.edu        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
79310447Snilay@cs.wisc.edu                " -> Downstream model does not exist");
79410447Snilay@cs.wisc.edu
79510447Snilay@cs.wisc.edu        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info_);
79610447Snilay@cs.wisc.edu        return;
79710447Snilay@cs.wisc.edu    }
79810447Snilay@cs.wisc.edu
79910447Snilay@cs.wisc.edu    void ElectricalModel::propagatePortTransitionInfo(const String& downstream_port_name_, const String& upstream_port_name_)
80010447Snilay@cs.wisc.edu    {
80110447Snilay@cs.wisc.edu        const TransitionInfo& trans_info = getInputPort(upstream_port_name_)->getTransitionInfo();
80210447Snilay@cs.wisc.edu        getOutputPort(downstream_port_name_)->setTransitionInfo(trans_info);
80310447Snilay@cs.wisc.edu        return;
80410447Snilay@cs.wisc.edu    }
80510447Snilay@cs.wisc.edu
80610447Snilay@cs.wisc.edu    void ElectricalModel::propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const String& upstream_port_name_)
80710447Snilay@cs.wisc.edu    {
80810447Snilay@cs.wisc.edu        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
80910447Snilay@cs.wisc.edu                " -> Downstream model does not exist");
81010447Snilay@cs.wisc.edu
81110447Snilay@cs.wisc.edu        const TransitionInfo& trans_info = getInputPort(upstream_port_name_)->getTransitionInfo();
81210447Snilay@cs.wisc.edu        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info);
81310447Snilay@cs.wisc.edu        return;
81410447Snilay@cs.wisc.edu    }
81510447Snilay@cs.wisc.edu
81610447Snilay@cs.wisc.edu    void ElectricalModel::propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_)
81710447Snilay@cs.wisc.edu    {
81810447Snilay@cs.wisc.edu        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
81910447Snilay@cs.wisc.edu                " -> Downstream model does not exist");
82010447Snilay@cs.wisc.edu        ASSERT(upstream_model_ != NULL, "[Error] " + getInstanceName() +
82110447Snilay@cs.wisc.edu                " -> Upstream model does not exist");
82210447Snilay@cs.wisc.edu
82310447Snilay@cs.wisc.edu        const TransitionInfo& trans_info = upstream_model_->getOutputPort(upstream_port_name_)->getTransitionInfo();
82410447Snilay@cs.wisc.edu
82510447Snilay@cs.wisc.edu        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info);
82610447Snilay@cs.wisc.edu        return;
82710447Snilay@cs.wisc.edu    }
82810447Snilay@cs.wisc.edu
82910447Snilay@cs.wisc.edu    void ElectricalModel::propagatePortTransitionInfo(const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_)
83010447Snilay@cs.wisc.edu    {
83110447Snilay@cs.wisc.edu        ASSERT(upstream_model_ != NULL, "[Error] " + getInstanceName() +
83210447Snilay@cs.wisc.edu                " -> Upstream model does not exist");
83310447Snilay@cs.wisc.edu
83410447Snilay@cs.wisc.edu        const TransitionInfo& trans_info = upstream_model_->getOutputPort(upstream_port_name_)->getTransitionInfo();
83510447Snilay@cs.wisc.edu        getOutputPort(downstream_port_name_)->setTransitionInfo(trans_info);
83610447Snilay@cs.wisc.edu        return;
83710447Snilay@cs.wisc.edu    }
83810447Snilay@cs.wisc.edu
83910447Snilay@cs.wisc.edu    void ElectricalModel::propagateTransitionInfo()
84010447Snilay@cs.wisc.edu    {
84110447Snilay@cs.wisc.edu        // by default do nothing.
84210447Snilay@cs.wisc.edu    }
84310447Snilay@cs.wisc.edu
84410447Snilay@cs.wisc.edu    void ElectricalModel::useModel(const String& event_name_)
84510447Snilay@cs.wisc.edu    {
84610447Snilay@cs.wisc.edu        getGenProperties()->set("UseModelEvent", event_name_);
84710447Snilay@cs.wisc.edu        applyTransitionInfo(event_name_);
84810447Snilay@cs.wisc.edu        useModel();
84910447Snilay@cs.wisc.edu        return;
85010447Snilay@cs.wisc.edu    }
85110447Snilay@cs.wisc.edu
85210447Snilay@cs.wisc.edu    void ElectricalModel::useModel()
85310447Snilay@cs.wisc.edu    {
85410447Snilay@cs.wisc.edu        propagateTransitionInfo();
85510447Snilay@cs.wisc.edu        return;
85610447Snilay@cs.wisc.edu    }
85710447Snilay@cs.wisc.edu
85810447Snilay@cs.wisc.edu    void ElectricalModel::applyTransitionInfo(const String& event_name_)
85910447Snilay@cs.wisc.edu    {
86010447Snilay@cs.wisc.edu        // Check if the event actually exists
86110447Snilay@cs.wisc.edu        ASSERT(hasEventResult(event_name_), "[Error] " + getInstanceName() +
86210447Snilay@cs.wisc.edu                " -> Event (" + event_name_ + ") does not exist in the result map");
86310447Snilay@cs.wisc.edu        ASSERT(m_event_infos_->keyExist(event_name_), "[Error] " + getInstanceName() +
86410447Snilay@cs.wisc.edu                " -> Event (" + event_name_ + ") does not exist in the event info map");
86510447Snilay@cs.wisc.edu
86610447Snilay@cs.wisc.edu        const EventInfo* event_info = m_event_infos_->get(event_name_);
86710447Snilay@cs.wisc.edu
86810447Snilay@cs.wisc.edu        // Set the input ports' transition information for the event
86910447Snilay@cs.wisc.edu        Map<PortInfo*>::ConstIterator it_begin = m_input_ports_->begin();
87010447Snilay@cs.wisc.edu        Map<PortInfo*>::ConstIterator it_end = m_input_ports_->end();
87110447Snilay@cs.wisc.edu        Map<PortInfo*>::ConstIterator it;
87210447Snilay@cs.wisc.edu        for(it = it_begin; it != it_end; ++it)
87310447Snilay@cs.wisc.edu        {
87410447Snilay@cs.wisc.edu            const String& port_name = it->first;
87510447Snilay@cs.wisc.edu            PortInfo* port_info = it->second;
87610447Snilay@cs.wisc.edu            const TransitionInfo& trans_info = event_info->getTransitionInfo(port_name);
87710447Snilay@cs.wisc.edu            port_info->setTransitionInfo(trans_info);
87810447Snilay@cs.wisc.edu        }
87910447Snilay@cs.wisc.edu
88010447Snilay@cs.wisc.edu        return;
88110447Snilay@cs.wisc.edu    }
88210447Snilay@cs.wisc.edu
88310447Snilay@cs.wisc.edu    EventInfo* ElectricalModel::getEventInfo(const String& event_name_)
88410447Snilay@cs.wisc.edu    {
88510447Snilay@cs.wisc.edu        ASSERT(m_event_infos_->keyExist(event_name_), "[Error] " + getInstanceName() +
88610447Snilay@cs.wisc.edu                " -> Event (" + event_name_ + ") does not exist");
88710447Snilay@cs.wisc.edu
88810447Snilay@cs.wisc.edu        return m_event_infos_->get(event_name_);
88910447Snilay@cs.wisc.edu    }
89010447Snilay@cs.wisc.edu
89110447Snilay@cs.wisc.edu} // namespace DSENT
89210447Snilay@cs.wisc.edu
893