ElectricalModel.cc revision 10447:a465576671d4
1754SN/A#include "model/ElectricalModel.h"
21762SN/A
3754SN/A#include "model/PortInfo.h"
4754SN/A#include "model/EventInfo.h"
5754SN/A#include "model/timing_graph/ElectricalDriver.h"
6754SN/A#include "model/timing_graph/ElectricalDriverMultiplier.h"
7754SN/A#include "model/timing_graph/ElectricalNet.h"
8754SN/A#include "model/timing_graph/ElectricalLoad.h"
9754SN/A#include "model/timing_graph/ElectricalDelay.h"
10754SN/A
11754SN/Anamespace DSENT
12754SN/A{
13754SN/A    ElectricalModel::ElectricalModel(const String& instance_name_, const TechModel* tech_model_)
14754SN/A        : Model(instance_name_, tech_model_)
15754SN/A    {
16754SN/A        m_curr_driving_strengths_idx_ = -1;
17754SN/A        m_input_ports_ = new Map<PortInfo*>;
18754SN/A        m_output_ports_ = new Map<PortInfo*>;
19754SN/A        m_net_references_ = new Map<NetIndex>;
20754SN/A        m_drivers_ = new Map<ElectricalDriver*>;
21754SN/A        m_driver_multipliers_ = new Map<ElectricalDriverMultiplier*>;
22754SN/A        m_nets_ = new Map<ElectricalNet*>;
23754SN/A        m_loads_ = new Map<ElectricalLoad*>;
24754SN/A        m_delays_ = new Map<ElectricalDelay*>;
25754SN/A        m_event_infos_ = new Map<EventInfo*>;
26754SN/A    }
272665Ssaidi@eecs.umich.edu
282665Ssaidi@eecs.umich.edu    ElectricalModel::~ElectricalModel()
292665Ssaidi@eecs.umich.edu    {
30754SN/A        deletePtrMap<PortInfo>(m_input_ports_);
31754SN/A        deletePtrMap<PortInfo>(m_output_ports_);
32754SN/A        delete m_net_references_;
33754SN/A        deletePtrMap<ElectricalDriver>(m_drivers_);
34754SN/A        deletePtrMap<ElectricalDriverMultiplier>(m_driver_multipliers_);
351070SN/A        deletePtrMap<ElectricalNet>(m_nets_);
361070SN/A        deletePtrMap<ElectricalLoad>(m_loads_);
37754SN/A        deletePtrMap<ElectricalDelay>(m_delays_);
381070SN/A        deletePtrMap<EventInfo>(m_event_infos_);
39754SN/A        m_input_ports_ = NULL;
401917SN/A        m_output_ports_ = NULL;
411917SN/A        m_net_references_ = NULL;
421070SN/A        m_drivers_ = NULL;
43754SN/A        m_driver_multipliers_ = NULL;
441070SN/A        m_nets_ = NULL;
451681SN/A        m_loads_ = NULL;
461681SN/A        m_net_references_ = NULL;
47754SN/A        m_event_infos_ = NULL;
481070SN/A    }
491070SN/A
501082SN/A    void ElectricalModel::checkProperties() const
511070SN/A    {
521070SN/A        // Check if the specified driving strength exists in the available driving strengths
531070SN/A        if(getProperties()->keyExist("DrivingStrength"))
54754SN/A        {
55754SN/A            const double driving_strength = getProperty("DrivingStrength");
561070SN/A            bool is_found = false;
571070SN/A            for(int i = 0; i < (int)m_driving_strengths_.size(); ++i)
581070SN/A            {
591070SN/A                if(driving_strength == m_driving_strengths_[i])
601070SN/A                {
611070SN/A                    is_found = true;
621070SN/A                    break;
631070SN/A                }
641070SN/A            }
651070SN/A            ASSERT(is_found, "[Error] " + getInstanceName() +
661070SN/A                " -> Driving strength (" + String(driving_strength) + ")"
671070SN/A                " not found in available driving strengths (" +
681070SN/A                getParameter("AvailableDrivingStrengths"));
691070SN/A        }
701070SN/A
711070SN/A        // Do normal check on the properties
721070SN/A        Model::checkProperties();
731070SN/A        return;
741070SN/A    }
751070SN/A
761070SN/A    double ElectricalModel::getDrivingStrength() const
771070SN/A    {
781070SN/A        if(m_curr_driving_strengths_idx_ == -1)
791070SN/A        {
801070SN/A            return 0;
811070SN/A        }
821070SN/A        else
831070SN/A        {
841070SN/A            return m_driving_strengths_[m_curr_driving_strengths_idx_];
851070SN/A        }
861070SN/A    }
871070SN/A
881070SN/A    int ElectricalModel::getDrivingStrengthIdx() const
891070SN/A    {
901070SN/A        return m_curr_driving_strengths_idx_;
911070SN/A    }
921070SN/A
931070SN/A    void ElectricalModel::setDrivingStrengthIdx(int idx_)
941070SN/A    {
951070SN/A        ASSERT(((idx_ >= 0) && (idx_ < (int)m_driving_strengths_.size())),
961070SN/A                "[Error] " + getInstanceName() +
971070SN/A                " -> Driving strength index out of range (" + String(idx_) + ")");
981070SN/A
991070SN/A        m_curr_driving_strengths_idx_ = idx_;
1001070SN/A        setProperty("DrivingStrength", m_driving_strengths_[m_curr_driving_strengths_idx_]);
1011070SN/A
1021070SN/A        Log::printLine(getInstanceName() + " -> Changing drive strength to " + (String) m_driving_strengths_[m_curr_driving_strengths_idx_]);
1031082SN/A        update();
104754SN/A        return;
105754SN/A    }
1061070SN/A
1071070SN/A    void ElectricalModel::setMinDrivingStrength()
108754SN/A    {
1091070SN/A        setDrivingStrengthIdx(0);
1101070SN/A        return;
1112107SN/A    }
1121070SN/A
1131070SN/A    bool ElectricalModel::hasMinDrivingStrength() const
1141070SN/A    {
1151070SN/A        return (m_curr_driving_strengths_idx_ == 0);
1161070SN/A    }
1171070SN/A
1181070SN/A    bool ElectricalModel::hasMaxDrivingStrength() const
1191070SN/A    {
120754SN/A        return (m_curr_driving_strengths_idx_ == ((int)m_driving_strengths_.size() - 1));
121754SN/A    }
1221070SN/A
1231070SN/A    void ElectricalModel::increaseDrivingStrength()
1241070SN/A    {
125754SN/A        if(!hasMaxDrivingStrength())
126754SN/A        {
1271070SN/A            setDrivingStrengthIdx(m_curr_driving_strengths_idx_ + 1);
1281070SN/A        }
1292107SN/A        return;
1301070SN/A    }
1311070SN/A
1321070SN/A    void ElectricalModel::decreaseDrivingStrength()
1331070SN/A    {
1341070SN/A        if(!hasMinDrivingStrength())
1351070SN/A        {
1361070SN/A            setDrivingStrengthIdx(m_curr_driving_strengths_idx_ - 1);
1371070SN/A        }
1381082SN/A        return;
1391070SN/A    }
1402190SN/A
1411070SN/A    void ElectricalModel::setAvailableDrivingStrengths(const String& driving_strengths_)
1421070SN/A    {
1431070SN/A        setParameter("AvailableDrivingStrengths", driving_strengths_);
1441070SN/A        const vector<String>& split_str = driving_strengths_.split("[,");
1451070SN/A
1461070SN/A        // Check if there is at least one driving strength specified
1471070SN/A        ASSERT(!split_str.empty(), "[Error] " + getInstanceName() +
1481070SN/A            " -> Specified driving strength string does not contain any driving strengths (" +
1491070SN/A            driving_strengths_ + ")");
1501070SN/A
1511070SN/A        // TODO - check if the driving strengths is sorted
1521070SN/A
1531070SN/A        // Overwrite the available driving strengths
1541070SN/A        m_driving_strengths_.clear();
1551070SN/A        for(int i = 0; i < (int)split_str.size(); ++i)
1562147SN/A        {
1571070SN/A            m_driving_strengths_.push_back(split_str[i].toDouble());
1581070SN/A        }
1591070SN/A
1601070SN/A        // Set the driving strength to minimum
1611070SN/A        m_curr_driving_strengths_idx_ = 0;
1621070SN/A        setProperty("DrivingStrength", m_driving_strengths_[m_curr_driving_strengths_idx_]);
1631070SN/A        return;
1641070SN/A    }
1651070SN/A
1661070SN/A    // Connect a port (input or output) to some ElectricalNet
1671070SN/A    void ElectricalModel::portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_)
1681070SN/A    {
1691070SN/A        ASSERT(m_net_references_->keyExist(connect_net_name_), "[Error] " + getInstanceName() +
1702190SN/A            " -> Net '" + connect_net_name_ + "' does not exist!");
1711070SN/A
1721070SN/A        portConnect(connect_model_, connect_port_name_, connect_net_name_, m_net_references_->get(connect_net_name_));
1731070SN/A    }
1741070SN/A
1751070SN/A    void ElectricalModel::portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_, const NetIndex& connect_net_indices_)
1761070SN/A    {
1771070SN/A        ASSERT(m_net_references_->keyExist(connect_net_name_), "[Error] " + getInstanceName() +
1781070SN/A            " -> Net '" + connect_net_name_ + "' does not exist!");
1791070SN/A
1801070SN/A        // Check whether the port name is an input or output, ASSERTion error if neither
1811070SN/A        bool is_input = connect_model_->getInputs()->keyExist(connect_port_name_);
1822190SN/A        bool is_output = connect_model_->getOutputs()->keyExist(connect_port_name_);
1832190SN/A
1842190SN/A        ASSERT(is_input || is_output, "[Error] " + getInstanceName() + " -> Model '" + connect_model_->getInstanceName() +
1851070SN/A            "' does not have a port named '" + connect_port_name_ + "'!");
1862190SN/A
1871070SN/A        int connect_net_width = connect_net_indices_.second - connect_net_indices_.first + 1;
1881070SN/A        const NetIndex& port_indices = connect_model_->getNetReference(connect_port_name_);
1891070SN/A        int port_width = port_indices.second - port_indices.first + 1;
1901070SN/A
1911070SN/A        ASSERT(connect_net_width == port_width, "[Error] " + getInstanceName() + " -> Port width mismatch for Model '" +
1921070SN/A            connect_model_->getInstanceName() + "." + connect_port_name_ + toString(port_indices) +
1931070SN/A            "' and net '" + connect_net_name_ + toString(connect_net_indices_) + "'!");
1941070SN/A
195754SN/A        int port_index = port_indices.first;
196        int connect_net_index = connect_net_indices_.first;
197
198        if(is_input)
199        {
200            while(port_index <= port_indices.second)
201            {
202                getNet(connect_net_name_, makeNetIndex(connect_net_index))->addDownstreamNode(
203                    connect_model_->getNet(connect_port_name_, makeNetIndex(port_index)));
204                ++port_index;
205                ++connect_net_index;
206            }
207        }
208        else if(is_output)
209        {
210            while (port_index <= port_indices.second)
211            {
212                connect_model_->getNet(connect_port_name_, makeNetIndex(port_index))->addDownstreamNode(
213                    getNet(connect_net_name_, makeNetIndex(connect_net_index)));
214                ++port_index;
215                ++connect_net_index;
216            }
217        }
218    }
219
220    //Get Drivers
221    const Map<ElectricalDriver*>* ElectricalModel::getDrivers() const
222    {
223        return m_drivers_;
224    }
225
226    ElectricalDriver* ElectricalModel::getDriver(const String& name_)
227    {
228        return m_drivers_->get(name_);
229    }
230
231    //Get Driver Multipliers
232    const Map<ElectricalDriverMultiplier*>* ElectricalModel::getDriverMultipliers() const
233    {
234        return m_driver_multipliers_;
235    }
236
237    ElectricalDriverMultiplier* ElectricalModel::getDriverMultiplier(const String& name_)
238    {
239        return m_driver_multipliers_->get(name_);
240    }
241
242    //Get Nets
243    const Map<ElectricalNet*>* ElectricalModel::getNets() const
244    {
245        return m_nets_;
246    }
247
248    ElectricalNet* ElectricalModel::getNet(const String& name_)
249    {
250        return getNet(name_, m_net_references_->get(name_));
251    }
252
253    ElectricalNet* ElectricalModel::getNet(const String& name_, const NetIndex& index_)
254    {
255        ASSERT(index_.first == index_.second, "[Error] " + getInstanceName() +
256            " -> Ambiguous get net since (" + name_ + ") is a bus consisting of several nets!");
257        return m_nets_->get(name_ + "[" + (String) index_.first + "]");
258    }
259
260    //Get Loads
261    const Map<ElectricalLoad*>* ElectricalModel::getLoads() const
262    {
263        return m_loads_;
264    }
265
266    ElectricalLoad* ElectricalModel::getLoad(const String& name_)
267    {
268        return m_loads_->get(name_);
269    }
270
271    //Get Delays
272    const Map<ElectricalDelay*>* ElectricalModel::getDelays() const
273    {
274        return m_delays_;
275    }
276
277    ElectricalDelay* ElectricalModel::getDelay(const String& name_)
278    {
279        return m_delays_->get(name_);
280    }
281
282    //Get Inputs
283    const Map<PortInfo*>* ElectricalModel::getInputs() const
284    {
285        return m_input_ports_;
286    }
287
288    PortInfo* ElectricalModel::getInputPort(const String& name_)
289    {
290        ASSERT(m_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
291                " -> Input port (" + name_ + ") does not exist");
292
293        return m_input_ports_->get(name_);
294    }
295
296    const PortInfo* ElectricalModel::getInputPort(const String& name_) const
297    {
298        ASSERT(m_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
299                " -> Input port (" + name_ + ") does not exist");
300
301        return m_input_ports_->get(name_);
302    }
303
304    //Get Outputs
305    const Map<PortInfo*>* ElectricalModel::getOutputs() const
306    {
307        return m_output_ports_;
308    }
309
310    PortInfo* ElectricalModel::getOutputPort(const String& name_)
311    {
312        ASSERT(m_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
313                " -> Output port (" + name_ + ") does not exist");
314
315        return m_output_ports_->get(name_);
316    }
317
318    const PortInfo* ElectricalModel::getOutputPort(const String& name_) const
319    {
320        ASSERT(m_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
321                " -> Output port (" + name_ + ") does not exist");
322
323        return m_output_ports_->get(name_);
324    }
325
326    const Map<NetIndex>* ElectricalModel::getNetReferences() const
327    {
328        return m_net_references_;
329    }
330
331    const NetIndex ElectricalModel::getNetReference(const String& name_) const
332    {
333        return m_net_references_->get(name_);
334    }
335
336    //-------------------------------------------------------------------------
337    //  Electrical Connectivity and Timing Element Creation Functions
338    //-------------------------------------------------------------------------
339
340    // Input Port creation
341    void ElectricalModel::createInputPort(const String& name_, const NetIndex& net_indices_)
342    {
343        // Create the new nets (including its net reference)
344        // This should already check that it has not been previously declared
345        createNet(name_, net_indices_);
346        // Add the net name to list of input ports
347        m_input_ports_->set(name_, new PortInfo(name_, net_indices_));
348        return;
349    }
350
351    // Output Port creation
352    void ElectricalModel::createOutputPort(const String& name_, const NetIndex& net_indices_)
353    {
354        // Create the new nets (including its net reference)
355        // This should already check that it has not been previously declared
356        createNet(name_, net_indices_);
357        // Add the net name to list of output ports
358        m_output_ports_->set(name_, new PortInfo(name_, net_indices_));
359        return;
360    }
361
362    // Net creation
363    void ElectricalModel::createNet(const String& name_)
364    {
365        // Creating a net with specifying an index range means that the net is just
366        // a 1-bit wire indexed at [0]
367        createNet(name_, makeNetIndex(0, 0));
368        return;
369    }
370
371    void ElectricalModel::createNet(const String& name_, const NetIndex& net_indices_)
372    {
373        // Check that it hasn't been previously declared
374        ASSERT( !m_nets_->keyExist(name_) && !m_net_references_->keyExist(name_),
375                "[Error] " + getInstanceName() + " -> Redeclaration of net " + name_);
376
377        int start = net_indices_.first;
378        int end = net_indices_.second;
379
380        for (int index = start; index <= end; ++index)
381        {
382            String indexed_name = name_ + "[" + (String) index + "]";
383            // Create the new net
384            ElectricalNet* net = new ElectricalNet(indexed_name, this);
385            // Add the net to net map
386            m_nets_->set(indexed_name, net);
387        }
388        // Add net to net references
389        m_net_references_->set(name_, net_indices_);
390        return;
391    }
392
393    // Driver creation
394    void ElectricalModel::createDriver(const String& name_, bool sizable_)
395    {
396        // Check that it hasn't been previously declared
397        ASSERT( !m_drivers_->keyExist(name_),
398                "[Error] " + getInstanceName() + " -> Redeclaration of driver " + name_);
399
400        ElectricalDriver* driver = new ElectricalDriver(name_, this, sizable_);
401        m_drivers_->set(name_, driver);
402        return;
403    }
404
405    /*
406    void ElectricalModel::createDriver(const String& name_, bool sizable_, int start_index_, int end_index_)
407    {
408        for (int index = start_index_; index <= end_index_; ++index)
409        {
410            createDriver(name_ + "[" + (String) index + "]", sizable_);
411        }
412        return;
413    }
414    */
415
416    // Driver Multiplier creation
417    void ElectricalModel::createDriverMultiplier(const String& name_)
418    {
419        // Check that it hasn't been previously declared
420        ASSERT( !m_driver_multipliers_->keyExist(name_),
421                "[Error] " + getInstanceName() + " -> Redeclaration of driver_multiplier " + name_);
422
423        ElectricalDriverMultiplier* driver_multiplier = new ElectricalDriverMultiplier(name_, this);
424        m_driver_multipliers_->set(name_, driver_multiplier);
425        return;
426    }
427
428    // Load creation
429
430    void ElectricalModel::createLoad(const String& name_)
431    {
432        // Check that it hasn't been previously declared
433        ASSERT( !m_loads_->keyExist(name_),
434                "[Error] " + getInstanceName() + " -> Redeclaration of load " + name_);
435
436        ElectricalLoad* load = new ElectricalLoad(name_, this);
437        m_loads_->set(name_, load);
438        return;
439    }
440
441    /*
442    void ElectricalModel::createLoad(const String& name_, int start_index_, int end_index_)
443    {
444        for (int index = start_index_; index <= end_index_; ++index)
445        {
446            createLoad(name_ + "[" + (String) index + "]");
447        }
448        return;
449    }
450    */
451
452    // Delay creation
453    void ElectricalModel::createDelay(const String& name_)
454    {
455        // Check that it hasn't been previously declared
456        ASSERT( !m_delays_->keyExist(name_),
457                "[Error] " + getInstanceName() + " -> Redeclaration of delay " + name_);
458
459        ElectricalDelay* delay = new ElectricalDelay(name_, this);
460        m_delays_->set(name_, delay);
461        return;
462    }
463
464    /*
465    void ElectricalModel::createDelay(const String& name_, int start_index_, int end_index_)
466    {
467        for (int index = start_index_; index <= end_index_; ++index)
468        {
469            createDelay(name_ + "[" + (String) index + "]");
470        }
471        return;
472    }
473    */
474    //-------------------------------------------------------------------------
475
476    // Assign a net to be downstream from another net
477    // case 1: 'assign downstream_net_name_ = upstream_net_name_'
478    void ElectricalModel::assign(const String& downstream_net_name_, const String& upstream_net_name_)
479    {
480        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
481            downstream_net_name_ + "' does not exist!");
482
483        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
484            upstream_net_name_ + "' does not exist!");
485
486        assign(downstream_net_name_, getNetReference(downstream_net_name_),
487            upstream_net_name_, getNetReference(upstream_net_name_));
488
489        return;
490    }
491
492    // case 2: 'assign downstream_net_name_[begin:end] = upstream_net_name_'
493    void ElectricalModel::assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_)
494    {
495        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
496            downstream_net_name_ + "' does not exist!");
497
498        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
499            upstream_net_name_ + "' does not exist!");
500
501        assign(downstream_net_name_, downstream_net_indices_,
502            upstream_net_name_, getNetReference(upstream_net_name_));
503
504        return;
505    }
506
507    // case 3: 'assign downstream_net_name_ = upstream_net_name_[begin:end]'
508    void ElectricalModel::assign(const String& downstream_net_name_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
509    {
510        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
511            downstream_net_name_ + "' does not exist!");
512
513        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
514            upstream_net_name_ + "' does not exist!");
515
516        assign(downstream_net_name_, getNetReference(downstream_net_name_),
517            upstream_net_name_, upstream_net_indices_);
518
519        return;
520    }
521    // case 4: 'assign downstream_net_name_[begin:end] = upstream_net_name_[begin:end]'
522    void ElectricalModel::assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
523    {
524        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
525            downstream_net_name_ + "' does not exist!");
526
527        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
528            upstream_net_name_ + "' does not exist!");
529
530        // Check that the assignment widths are the same
531        int downstream_width = downstream_net_indices_.second - downstream_net_indices_.first + 1;
532        int upstream_width = upstream_net_indices_.second - upstream_net_indices_.first + 1;
533
534        ASSERT(downstream_width == upstream_width, "[Error] " + getInstanceName() + " -> Assignment width mismatch: " +
535            downstream_net_name_ + " (" + (String) downstream_width + ") and " +
536            upstream_net_name_ + " (" + (String) upstream_width + ")");
537
538        // Loop through indices and connect them together
539        int down_index = downstream_net_indices_.first;
540        int up_index = upstream_net_indices_.first;
541        while (down_index <= downstream_net_indices_.second)
542        {
543            getNet(upstream_net_name_, makeNetIndex(up_index))->addDownstreamNode(
544                getNet(downstream_net_name_, makeNetIndex(down_index)));
545
546            ++up_index;
547            ++down_index;
548        }
549
550        return;
551    }
552
553    // Assign a net to another net through a driver multiplier
554    void ElectricalModel::assignVirtualFanout(const String& downstream_net_name_, const String& upstream_net_name_)
555    {
556        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
557                " -> Net '" + upstream_net_name_ + "' does not exist!");
558        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
559                " -> Net '" + downstream_net_name_ + "' does not exist!");
560
561        assignVirtualFanout(downstream_net_name_, getNetReference(downstream_net_name_), upstream_net_name_, getNetReference(upstream_net_name_));
562        return;
563    }
564
565    // Assign a net to another net through a driver multiplier
566    void ElectricalModel::assignVirtualFanout(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
567    {
568        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
569                " -> Net '" + upstream_net_name_ + "' does not exist!");
570        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
571                " -> Net '" + downstream_net_name_ + "' does not exist!");
572
573        const String& drive_mult_name = upstream_net_name_ + "_" + (String) upstream_net_indices_.first + "_DriverMultiplier";
574        bool is_drive_mult_exist = getDriverMultipliers()->keyExist(drive_mult_name);
575
576        // Create a driver multiplier and assign it to upstream_net since it doesn't exist
577        if(!is_drive_mult_exist)
578        {
579            createDriverMultiplier(drive_mult_name);
580            getNet(upstream_net_name_, upstream_net_indices_)->addDownstreamNode(getDriverMultiplier(drive_mult_name));
581        }
582
583        // Assign downstream_net_name_[end:begin] = driver_multiplier_name_
584        ElectricalDriverMultiplier* drive_mult = getDriverMultiplier(drive_mult_name);
585        int begin_index = downstream_net_indices_.first;
586        int end_index = downstream_net_indices_.second;
587        for(int i = begin_index; i <= end_index; ++i)
588        {
589            drive_mult->addDownstreamNode(getNet(downstream_net_name_, makeNetIndex(i)));
590        }
591        return;
592    }
593
594    void ElectricalModel::assignVirtualFanin(const String& downstream_net_name_, const String& upstream_net_name_)
595    {
596        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
597                " -> Net '" + upstream_net_name_ + "' does not exist!");
598        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
599                " -> Net '" + downstream_net_name_ + "' does not exist!");
600
601        assignVirtualFanin(downstream_net_name_, getNetReference(downstream_net_name_), upstream_net_name_, getNetReference(upstream_net_name_));
602        return;
603    }
604
605    void ElectricalModel::assignVirtualFanin(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
606    {
607        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
608                " -> Net '" + upstream_net_name_ + "' does not exist!");
609        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
610                " -> Net '" + downstream_net_name_ + "' does not exist!");
611
612        int begin_index = upstream_net_indices_.first;
613        int end_index = upstream_net_indices_.second;
614
615        for(int i = begin_index; i <= end_index; ++i)
616        {
617            getNet(upstream_net_name_, makeNetIndex(i))->addDownstreamNode(getNet(downstream_net_name_, downstream_net_indices_));
618        }
619        return;
620    }
621
622    void ElectricalModel::createElectricalResults()
623    {
624        // Add active area result
625        addAreaResult(new Result("Active"));
626
627        // Add wire area result
628        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
629        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
630        TechModel::ConstWireLayerIterator it;
631        for(it = it_begin; it != it_end; ++it)
632        {
633            const String& layer_name = (*it);
634            addAreaResult(new Result(layer_name + "Wire"));
635        }
636
637        // Add leakage result
638        addNddPowerResult(new Result("Leakage"));
639
640        // Add idle event result
641        createElectricalEventResult("Idle");
642        return;
643    }
644
645    void ElectricalModel::addElectricalSubResults(const ElectricalModel* model_, double number_models_)
646    {
647        // Add active area sub result
648        getAreaResult("Active")->addSubResult(model_->getAreaResult("Active"), model_->getInstanceName(), number_models_);
649
650        // Add wire area sub result
651        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
652        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
653        TechModel::ConstWireLayerIterator it;
654        for(it = it_begin; it != it_end; ++it)
655        {
656            const String& layer_name = (*it);
657            const String& result_name = layer_name + "Wire";
658            getAreaResult(result_name)->addSubResult(model_->getAreaResult(result_name), model_->getInstanceName(), number_models_);
659        }
660
661        // Add leakage sub result
662        getNddPowerResult("Leakage")->addSubResult(model_->getNddPowerResult("Leakage"), model_->getInstanceName(), number_models_);
663
664        // Add idle event sub result
665        getEventResult("Idle")->addSubResult(model_->getEventResult("Idle"), model_->getInstanceName(), number_models_);
666        return;
667    }
668
669    void ElectricalModel::addElectricalWireSubResult(const String& wire_layer_, const Result* result_, const String& producer_, double number_results_)
670    {
671        getAreaResult(wire_layer_ + "Wire")->addSubResult(result_, producer_, number_results_);
672        return;
673    }
674
675    void ElectricalModel::createElectricalAtomicResults()
676    {
677        // Add active area result
678        addAreaResult(new AtomicResult("Active"));
679
680        // Add wire area result
681        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
682        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
683        TechModel::ConstWireLayerIterator it;
684        for(it = it_begin; it != it_end; ++it)
685        {
686            const String& layer_name = (*it);
687            addAreaResult(new AtomicResult(layer_name + "Wire"));
688        }
689
690        // Add leakage result
691        addNddPowerResult(new AtomicResult("Leakage"));
692
693        // Add idle event result
694        createElectricalEventAtomicResult("Idle");
695        return;
696    }
697
698    void ElectricalModel::addElecticalAtomicResultValues(const ElectricalModel* model_, double number_models_)
699    {
700        getAreaResult("Active")->addValue(model_->getAreaResult("Active")->calculateSum() * number_models_);
701
702        // Add wire area sub result
703        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
704        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
705        TechModel::ConstWireLayerIterator it;
706        for(it = it_begin; it != it_end; ++it)
707        {
708            const String& layer_name = (*it);
709            const String& result_name = layer_name + "Wire";
710            getAreaResult(result_name)->addValue(model_->getAreaResult(result_name)->calculateSum() * number_models_);
711        }
712
713        // Add leakage sub result
714        getNddPowerResult("Leakage")->addValue(model_->getNddPowerResult("Leakage")->calculateSum() * number_models_);
715
716        // Add idle event sub result
717        getEventResult("Idle")->addValue(model_->getEventResult("Idle")->calculateSum() * number_models_);
718        return;
719    }
720
721    void ElectricalModel::addElecticalWireAtomicResultValue(const String& wire_layer_, double value_)
722    {
723        getAreaResult(wire_layer_ + "Wire")->addValue(value_);
724        return;
725    }
726
727    void ElectricalModel::resetElectricalAtomicResults()
728    {
729        getAreaResult("Active")->setValue(0.0);
730
731        // Reset wire area sub result
732        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
733        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
734        TechModel::ConstWireLayerIterator it;
735        for(it = it_begin; it != it_end; ++it)
736        {
737            const String& layer_name = (*it);
738            const String& result_name = layer_name + "Wire";
739            getAreaResult(result_name)->setValue(0.0);
740        }
741
742        // Reset leakage sub result
743        getNddPowerResult("Leakage")->setValue(0.0);
744
745        // Reset idle event sub result
746        getEventResult("Idle")->setValue(0.0);
747
748        return;
749    }
750
751    void ElectricalModel::createElectricalEventResult(const String& name_)
752    {
753        // Add the event result
754        addEventResult(new Result(name_));
755        // Add event info
756        m_event_infos_->set(name_, new EventInfo(name_, getInputs()));
757        return;
758    }
759
760    void ElectricalModel::createElectricalEventAtomicResult(const String& name_)
761    {
762        // Add the event result
763        addEventResult(new AtomicResult(name_));
764        // Add event info
765        m_event_infos_->set(name_, new EventInfo(name_, getInputs()));
766        return;
767    }
768
769    void ElectricalModel::assignPortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const TransitionInfo& trans_info_)
770    {
771        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
772                " -> Downstream model does not exist");
773
774        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info_);
775        return;
776    }
777
778    void ElectricalModel::propagatePortTransitionInfo(const String& downstream_port_name_, const String& upstream_port_name_)
779    {
780        const TransitionInfo& trans_info = getInputPort(upstream_port_name_)->getTransitionInfo();
781        getOutputPort(downstream_port_name_)->setTransitionInfo(trans_info);
782        return;
783    }
784
785    void ElectricalModel::propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const String& upstream_port_name_)
786    {
787        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
788                " -> Downstream model does not exist");
789
790        const TransitionInfo& trans_info = getInputPort(upstream_port_name_)->getTransitionInfo();
791        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info);
792        return;
793    }
794
795    void ElectricalModel::propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_)
796    {
797        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
798                " -> Downstream model does not exist");
799        ASSERT(upstream_model_ != NULL, "[Error] " + getInstanceName() +
800                " -> Upstream model does not exist");
801
802        const TransitionInfo& trans_info = upstream_model_->getOutputPort(upstream_port_name_)->getTransitionInfo();
803
804        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info);
805        return;
806    }
807
808    void ElectricalModel::propagatePortTransitionInfo(const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_)
809    {
810        ASSERT(upstream_model_ != NULL, "[Error] " + getInstanceName() +
811                " -> Upstream model does not exist");
812
813        const TransitionInfo& trans_info = upstream_model_->getOutputPort(upstream_port_name_)->getTransitionInfo();
814        getOutputPort(downstream_port_name_)->setTransitionInfo(trans_info);
815        return;
816    }
817
818    void ElectricalModel::propagateTransitionInfo()
819    {
820        // by default do nothing.
821    }
822
823    void ElectricalModel::useModel(const String& event_name_)
824    {
825        getGenProperties()->set("UseModelEvent", event_name_);
826        applyTransitionInfo(event_name_);
827        useModel();
828        return;
829    }
830
831    void ElectricalModel::useModel()
832    {
833        propagateTransitionInfo();
834        return;
835    }
836
837    void ElectricalModel::applyTransitionInfo(const String& event_name_)
838    {
839        // Check if the event actually exists
840        ASSERT(hasEventResult(event_name_), "[Error] " + getInstanceName() +
841                " -> Event (" + event_name_ + ") does not exist in the result map");
842        ASSERT(m_event_infos_->keyExist(event_name_), "[Error] " + getInstanceName() +
843                " -> Event (" + event_name_ + ") does not exist in the event info map");
844
845        const EventInfo* event_info = m_event_infos_->get(event_name_);
846
847        // Set the input ports' transition information for the event
848        Map<PortInfo*>::ConstIterator it_begin = m_input_ports_->begin();
849        Map<PortInfo*>::ConstIterator it_end = m_input_ports_->end();
850        Map<PortInfo*>::ConstIterator it;
851        for(it = it_begin; it != it_end; ++it)
852        {
853            const String& port_name = it->first;
854            PortInfo* port_info = it->second;
855            const TransitionInfo& trans_info = event_info->getTransitionInfo(port_name);
856            port_info->setTransitionInfo(trans_info);
857        }
858
859        return;
860    }
861
862    EventInfo* ElectricalModel::getEventInfo(const String& event_name_)
863    {
864        ASSERT(m_event_infos_->keyExist(event_name_), "[Error] " + getInstanceName() +
865                " -> Event (" + event_name_ + ") does not exist");
866
867        return m_event_infos_->get(event_name_);
868    }
869
870} // namespace DSENT
871
872