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