ElectricalModel.cc revision 10448
1/* Copyright (c) 2012 Massachusetts Institute of Technology
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 * THE SOFTWARE.
20 */
21
22#include "model/ElectricalModel.h"
23
24#include "model/PortInfo.h"
25#include "model/EventInfo.h"
26#include "model/timing_graph/ElectricalDriver.h"
27#include "model/timing_graph/ElectricalDriverMultiplier.h"
28#include "model/timing_graph/ElectricalNet.h"
29#include "model/timing_graph/ElectricalLoad.h"
30#include "model/timing_graph/ElectricalDelay.h"
31
32namespace DSENT
33{
34    ElectricalModel::ElectricalModel(const String& instance_name_, const TechModel* tech_model_)
35        : Model(instance_name_, tech_model_)
36    {
37        m_curr_driving_strengths_idx_ = -1;
38        m_input_ports_ = new Map<PortInfo*>;
39        m_output_ports_ = new Map<PortInfo*>;
40        m_net_references_ = new Map<NetIndex>;
41        m_drivers_ = new Map<ElectricalDriver*>;
42        m_driver_multipliers_ = new Map<ElectricalDriverMultiplier*>;
43        m_nets_ = new Map<ElectricalNet*>;
44        m_loads_ = new Map<ElectricalLoad*>;
45        m_delays_ = new Map<ElectricalDelay*>;
46        m_event_infos_ = new Map<EventInfo*>;
47    }
48
49    ElectricalModel::~ElectricalModel()
50    {
51        deletePtrMap<PortInfo>(m_input_ports_);
52        deletePtrMap<PortInfo>(m_output_ports_);
53        delete m_net_references_;
54        deletePtrMap<ElectricalDriver>(m_drivers_);
55        deletePtrMap<ElectricalDriverMultiplier>(m_driver_multipliers_);
56        deletePtrMap<ElectricalNet>(m_nets_);
57        deletePtrMap<ElectricalLoad>(m_loads_);
58        deletePtrMap<ElectricalDelay>(m_delays_);
59        deletePtrMap<EventInfo>(m_event_infos_);
60        m_input_ports_ = NULL;
61        m_output_ports_ = NULL;
62        m_net_references_ = NULL;
63        m_drivers_ = NULL;
64        m_driver_multipliers_ = NULL;
65        m_nets_ = NULL;
66        m_loads_ = NULL;
67        m_net_references_ = NULL;
68        m_event_infos_ = NULL;
69    }
70
71    void ElectricalModel::checkProperties() const
72    {
73        // Check if the specified driving strength exists in the available driving strengths
74        if(getProperties()->keyExist("DrivingStrength"))
75        {
76            const double driving_strength = getProperty("DrivingStrength");
77            bool is_found = false;
78            for(int i = 0; i < (int)m_driving_strengths_.size(); ++i)
79            {
80                if(driving_strength == m_driving_strengths_[i])
81                {
82                    is_found = true;
83                    break;
84                }
85            }
86            ASSERT(is_found, "[Error] " + getInstanceName() +
87                " -> Driving strength (" + String(driving_strength) + ")"
88                " not found in available driving strengths (" +
89                getParameter("AvailableDrivingStrengths"));
90        }
91
92        // Do normal check on the properties
93        Model::checkProperties();
94        return;
95    }
96
97    double ElectricalModel::getDrivingStrength() const
98    {
99        if(m_curr_driving_strengths_idx_ == -1)
100        {
101            return 0;
102        }
103        else
104        {
105            return m_driving_strengths_[m_curr_driving_strengths_idx_];
106        }
107    }
108
109    int ElectricalModel::getDrivingStrengthIdx() const
110    {
111        return m_curr_driving_strengths_idx_;
112    }
113
114    void ElectricalModel::setDrivingStrengthIdx(int idx_)
115    {
116        ASSERT(((idx_ >= 0) && (idx_ < (int)m_driving_strengths_.size())),
117                "[Error] " + getInstanceName() +
118                " -> Driving strength index out of range (" + String(idx_) + ")");
119
120        m_curr_driving_strengths_idx_ = idx_;
121        setProperty("DrivingStrength", m_driving_strengths_[m_curr_driving_strengths_idx_]);
122
123        Log::printLine(getInstanceName() + " -> Changing drive strength to " + (String) m_driving_strengths_[m_curr_driving_strengths_idx_]);
124        update();
125        return;
126    }
127
128    void ElectricalModel::setMinDrivingStrength()
129    {
130        setDrivingStrengthIdx(0);
131        return;
132    }
133
134    bool ElectricalModel::hasMinDrivingStrength() const
135    {
136        return (m_curr_driving_strengths_idx_ == 0);
137    }
138
139    bool ElectricalModel::hasMaxDrivingStrength() const
140    {
141        return (m_curr_driving_strengths_idx_ == ((int)m_driving_strengths_.size() - 1));
142    }
143
144    void ElectricalModel::increaseDrivingStrength()
145    {
146        if(!hasMaxDrivingStrength())
147        {
148            setDrivingStrengthIdx(m_curr_driving_strengths_idx_ + 1);
149        }
150        return;
151    }
152
153    void ElectricalModel::decreaseDrivingStrength()
154    {
155        if(!hasMinDrivingStrength())
156        {
157            setDrivingStrengthIdx(m_curr_driving_strengths_idx_ - 1);
158        }
159        return;
160    }
161
162    void ElectricalModel::setAvailableDrivingStrengths(const String& driving_strengths_)
163    {
164        setParameter("AvailableDrivingStrengths", driving_strengths_);
165        const vector<String>& split_str = driving_strengths_.split("[,");
166
167        // Check if there is at least one driving strength specified
168        ASSERT(!split_str.empty(), "[Error] " + getInstanceName() +
169            " -> Specified driving strength string does not contain any driving strengths (" +
170            driving_strengths_ + ")");
171
172        // TODO - check if the driving strengths is sorted
173
174        // Overwrite the available driving strengths
175        m_driving_strengths_.clear();
176        for(int i = 0; i < (int)split_str.size(); ++i)
177        {
178            m_driving_strengths_.push_back(split_str[i].toDouble());
179        }
180
181        // Set the driving strength to minimum
182        m_curr_driving_strengths_idx_ = 0;
183        setProperty("DrivingStrength", m_driving_strengths_[m_curr_driving_strengths_idx_]);
184        return;
185    }
186
187    // Connect a port (input or output) to some ElectricalNet
188    void ElectricalModel::portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_)
189    {
190        ASSERT(m_net_references_->keyExist(connect_net_name_), "[Error] " + getInstanceName() +
191            " -> Net '" + connect_net_name_ + "' does not exist!");
192
193        portConnect(connect_model_, connect_port_name_, connect_net_name_, m_net_references_->get(connect_net_name_));
194    }
195
196    void ElectricalModel::portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_, const NetIndex& connect_net_indices_)
197    {
198        ASSERT(m_net_references_->keyExist(connect_net_name_), "[Error] " + getInstanceName() +
199            " -> Net '" + connect_net_name_ + "' does not exist!");
200
201        // Check whether the port name is an input or output, ASSERTion error if neither
202        bool is_input = connect_model_->getInputs()->keyExist(connect_port_name_);
203        bool is_output = connect_model_->getOutputs()->keyExist(connect_port_name_);
204
205        ASSERT(is_input || is_output, "[Error] " + getInstanceName() + " -> Model '" + connect_model_->getInstanceName() +
206            "' does not have a port named '" + connect_port_name_ + "'!");
207
208        int connect_net_width = connect_net_indices_.second - connect_net_indices_.first + 1;
209        const NetIndex& port_indices = connect_model_->getNetReference(connect_port_name_);
210        int port_width = port_indices.second - port_indices.first + 1;
211
212        ASSERT(connect_net_width == port_width, "[Error] " + getInstanceName() + " -> Port width mismatch for Model '" +
213            connect_model_->getInstanceName() + "." + connect_port_name_ + toString(port_indices) +
214            "' and net '" + connect_net_name_ + toString(connect_net_indices_) + "'!");
215
216        int port_index = port_indices.first;
217        int connect_net_index = connect_net_indices_.first;
218
219        if(is_input)
220        {
221            while(port_index <= port_indices.second)
222            {
223                getNet(connect_net_name_, makeNetIndex(connect_net_index))->addDownstreamNode(
224                    connect_model_->getNet(connect_port_name_, makeNetIndex(port_index)));
225                ++port_index;
226                ++connect_net_index;
227            }
228        }
229        else if(is_output)
230        {
231            while (port_index <= port_indices.second)
232            {
233                connect_model_->getNet(connect_port_name_, makeNetIndex(port_index))->addDownstreamNode(
234                    getNet(connect_net_name_, makeNetIndex(connect_net_index)));
235                ++port_index;
236                ++connect_net_index;
237            }
238        }
239    }
240
241    //Get Drivers
242    const Map<ElectricalDriver*>* ElectricalModel::getDrivers() const
243    {
244        return m_drivers_;
245    }
246
247    ElectricalDriver* ElectricalModel::getDriver(const String& name_)
248    {
249        return m_drivers_->get(name_);
250    }
251
252    //Get Driver Multipliers
253    const Map<ElectricalDriverMultiplier*>* ElectricalModel::getDriverMultipliers() const
254    {
255        return m_driver_multipliers_;
256    }
257
258    ElectricalDriverMultiplier* ElectricalModel::getDriverMultiplier(const String& name_)
259    {
260        return m_driver_multipliers_->get(name_);
261    }
262
263    //Get Nets
264    const Map<ElectricalNet*>* ElectricalModel::getNets() const
265    {
266        return m_nets_;
267    }
268
269    ElectricalNet* ElectricalModel::getNet(const String& name_)
270    {
271        return getNet(name_, m_net_references_->get(name_));
272    }
273
274    ElectricalNet* ElectricalModel::getNet(const String& name_, const NetIndex& index_)
275    {
276        ASSERT(index_.first == index_.second, "[Error] " + getInstanceName() +
277            " -> Ambiguous get net since (" + name_ + ") is a bus consisting of several nets!");
278        return m_nets_->get(name_ + "[" + (String) index_.first + "]");
279    }
280
281    //Get Loads
282    const Map<ElectricalLoad*>* ElectricalModel::getLoads() const
283    {
284        return m_loads_;
285    }
286
287    ElectricalLoad* ElectricalModel::getLoad(const String& name_)
288    {
289        return m_loads_->get(name_);
290    }
291
292    //Get Delays
293    const Map<ElectricalDelay*>* ElectricalModel::getDelays() const
294    {
295        return m_delays_;
296    }
297
298    ElectricalDelay* ElectricalModel::getDelay(const String& name_)
299    {
300        return m_delays_->get(name_);
301    }
302
303    //Get Inputs
304    const Map<PortInfo*>* ElectricalModel::getInputs() const
305    {
306        return m_input_ports_;
307    }
308
309    PortInfo* ElectricalModel::getInputPort(const String& name_)
310    {
311        ASSERT(m_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
312                " -> Input port (" + name_ + ") does not exist");
313
314        return m_input_ports_->get(name_);
315    }
316
317    const PortInfo* ElectricalModel::getInputPort(const String& name_) const
318    {
319        ASSERT(m_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
320                " -> Input port (" + name_ + ") does not exist");
321
322        return m_input_ports_->get(name_);
323    }
324
325    //Get Outputs
326    const Map<PortInfo*>* ElectricalModel::getOutputs() const
327    {
328        return m_output_ports_;
329    }
330
331    PortInfo* ElectricalModel::getOutputPort(const String& name_)
332    {
333        ASSERT(m_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
334                " -> Output port (" + name_ + ") does not exist");
335
336        return m_output_ports_->get(name_);
337    }
338
339    const PortInfo* ElectricalModel::getOutputPort(const String& name_) const
340    {
341        ASSERT(m_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
342                " -> Output port (" + name_ + ") does not exist");
343
344        return m_output_ports_->get(name_);
345    }
346
347    const Map<NetIndex>* ElectricalModel::getNetReferences() const
348    {
349        return m_net_references_;
350    }
351
352    const NetIndex ElectricalModel::getNetReference(const String& name_) const
353    {
354        return m_net_references_->get(name_);
355    }
356
357    //-------------------------------------------------------------------------
358    //  Electrical Connectivity and Timing Element Creation Functions
359    //-------------------------------------------------------------------------
360
361    // Input Port creation
362    void ElectricalModel::createInputPort(const String& name_, const NetIndex& net_indices_)
363    {
364        // Create the new nets (including its net reference)
365        // This should already check that it has not been previously declared
366        createNet(name_, net_indices_);
367        // Add the net name to list of input ports
368        m_input_ports_->set(name_, new PortInfo(name_, net_indices_));
369        return;
370    }
371
372    // Output Port creation
373    void ElectricalModel::createOutputPort(const String& name_, const NetIndex& net_indices_)
374    {
375        // Create the new nets (including its net reference)
376        // This should already check that it has not been previously declared
377        createNet(name_, net_indices_);
378        // Add the net name to list of output ports
379        m_output_ports_->set(name_, new PortInfo(name_, net_indices_));
380        return;
381    }
382
383    // Net creation
384    void ElectricalModel::createNet(const String& name_)
385    {
386        // Creating a net with specifying an index range means that the net is just
387        // a 1-bit wire indexed at [0]
388        createNet(name_, makeNetIndex(0, 0));
389        return;
390    }
391
392    void ElectricalModel::createNet(const String& name_, const NetIndex& net_indices_)
393    {
394        // Check that it hasn't been previously declared
395        ASSERT( !m_nets_->keyExist(name_) && !m_net_references_->keyExist(name_),
396                "[Error] " + getInstanceName() + " -> Redeclaration of net " + name_);
397
398        int start = net_indices_.first;
399        int end = net_indices_.second;
400
401        for (int index = start; index <= end; ++index)
402        {
403            String indexed_name = name_ + "[" + (String) index + "]";
404            // Create the new net
405            ElectricalNet* net = new ElectricalNet(indexed_name, this);
406            // Add the net to net map
407            m_nets_->set(indexed_name, net);
408        }
409        // Add net to net references
410        m_net_references_->set(name_, net_indices_);
411        return;
412    }
413
414    // Driver creation
415    void ElectricalModel::createDriver(const String& name_, bool sizable_)
416    {
417        // Check that it hasn't been previously declared
418        ASSERT( !m_drivers_->keyExist(name_),
419                "[Error] " + getInstanceName() + " -> Redeclaration of driver " + name_);
420
421        ElectricalDriver* driver = new ElectricalDriver(name_, this, sizable_);
422        m_drivers_->set(name_, driver);
423        return;
424    }
425
426    /*
427    void ElectricalModel::createDriver(const String& name_, bool sizable_, int start_index_, int end_index_)
428    {
429        for (int index = start_index_; index <= end_index_; ++index)
430        {
431            createDriver(name_ + "[" + (String) index + "]", sizable_);
432        }
433        return;
434    }
435    */
436
437    // Driver Multiplier creation
438    void ElectricalModel::createDriverMultiplier(const String& name_)
439    {
440        // Check that it hasn't been previously declared
441        ASSERT( !m_driver_multipliers_->keyExist(name_),
442                "[Error] " + getInstanceName() + " -> Redeclaration of driver_multiplier " + name_);
443
444        ElectricalDriverMultiplier* driver_multiplier = new ElectricalDriverMultiplier(name_, this);
445        m_driver_multipliers_->set(name_, driver_multiplier);
446        return;
447    }
448
449    // Load creation
450
451    void ElectricalModel::createLoad(const String& name_)
452    {
453        // Check that it hasn't been previously declared
454        ASSERT( !m_loads_->keyExist(name_),
455                "[Error] " + getInstanceName() + " -> Redeclaration of load " + name_);
456
457        ElectricalLoad* load = new ElectricalLoad(name_, this);
458        m_loads_->set(name_, load);
459        return;
460    }
461
462    /*
463    void ElectricalModel::createLoad(const String& name_, int start_index_, int end_index_)
464    {
465        for (int index = start_index_; index <= end_index_; ++index)
466        {
467            createLoad(name_ + "[" + (String) index + "]");
468        }
469        return;
470    }
471    */
472
473    // Delay creation
474    void ElectricalModel::createDelay(const String& name_)
475    {
476        // Check that it hasn't been previously declared
477        ASSERT( !m_delays_->keyExist(name_),
478                "[Error] " + getInstanceName() + " -> Redeclaration of delay " + name_);
479
480        ElectricalDelay* delay = new ElectricalDelay(name_, this);
481        m_delays_->set(name_, delay);
482        return;
483    }
484
485    /*
486    void ElectricalModel::createDelay(const String& name_, int start_index_, int end_index_)
487    {
488        for (int index = start_index_; index <= end_index_; ++index)
489        {
490            createDelay(name_ + "[" + (String) index + "]");
491        }
492        return;
493    }
494    */
495    //-------------------------------------------------------------------------
496
497    // Assign a net to be downstream from another net
498    // case 1: 'assign downstream_net_name_ = upstream_net_name_'
499    void ElectricalModel::assign(const String& downstream_net_name_, const String& upstream_net_name_)
500    {
501        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
502            downstream_net_name_ + "' does not exist!");
503
504        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
505            upstream_net_name_ + "' does not exist!");
506
507        assign(downstream_net_name_, getNetReference(downstream_net_name_),
508            upstream_net_name_, getNetReference(upstream_net_name_));
509
510        return;
511    }
512
513    // case 2: 'assign downstream_net_name_[begin:end] = upstream_net_name_'
514    void ElectricalModel::assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_)
515    {
516        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
517            downstream_net_name_ + "' does not exist!");
518
519        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
520            upstream_net_name_ + "' does not exist!");
521
522        assign(downstream_net_name_, downstream_net_indices_,
523            upstream_net_name_, getNetReference(upstream_net_name_));
524
525        return;
526    }
527
528    // case 3: 'assign downstream_net_name_ = upstream_net_name_[begin:end]'
529    void ElectricalModel::assign(const String& downstream_net_name_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
530    {
531        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
532            downstream_net_name_ + "' does not exist!");
533
534        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
535            upstream_net_name_ + "' does not exist!");
536
537        assign(downstream_net_name_, getNetReference(downstream_net_name_),
538            upstream_net_name_, upstream_net_indices_);
539
540        return;
541    }
542    // case 4: 'assign downstream_net_name_[begin:end] = upstream_net_name_[begin:end]'
543    void ElectricalModel::assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
544    {
545        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
546            downstream_net_name_ + "' does not exist!");
547
548        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
549            upstream_net_name_ + "' does not exist!");
550
551        // Check that the assignment widths are the same
552        int downstream_width = downstream_net_indices_.second - downstream_net_indices_.first + 1;
553        int upstream_width = upstream_net_indices_.second - upstream_net_indices_.first + 1;
554
555        ASSERT(downstream_width == upstream_width, "[Error] " + getInstanceName() + " -> Assignment width mismatch: " +
556            downstream_net_name_ + " (" + (String) downstream_width + ") and " +
557            upstream_net_name_ + " (" + (String) upstream_width + ")");
558
559        // Loop through indices and connect them together
560        int down_index = downstream_net_indices_.first;
561        int up_index = upstream_net_indices_.first;
562        while (down_index <= downstream_net_indices_.second)
563        {
564            getNet(upstream_net_name_, makeNetIndex(up_index))->addDownstreamNode(
565                getNet(downstream_net_name_, makeNetIndex(down_index)));
566
567            ++up_index;
568            ++down_index;
569        }
570
571        return;
572    }
573
574    // Assign a net to another net through a driver multiplier
575    void ElectricalModel::assignVirtualFanout(const String& downstream_net_name_, const String& upstream_net_name_)
576    {
577        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
578                " -> Net '" + upstream_net_name_ + "' does not exist!");
579        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
580                " -> Net '" + downstream_net_name_ + "' does not exist!");
581
582        assignVirtualFanout(downstream_net_name_, getNetReference(downstream_net_name_), upstream_net_name_, getNetReference(upstream_net_name_));
583        return;
584    }
585
586    // Assign a net to another net through a driver multiplier
587    void ElectricalModel::assignVirtualFanout(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
588    {
589        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
590                " -> Net '" + upstream_net_name_ + "' does not exist!");
591        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
592                " -> Net '" + downstream_net_name_ + "' does not exist!");
593
594        const String& drive_mult_name = upstream_net_name_ + "_" + (String) upstream_net_indices_.first + "_DriverMultiplier";
595        bool is_drive_mult_exist = getDriverMultipliers()->keyExist(drive_mult_name);
596
597        // Create a driver multiplier and assign it to upstream_net since it doesn't exist
598        if(!is_drive_mult_exist)
599        {
600            createDriverMultiplier(drive_mult_name);
601            getNet(upstream_net_name_, upstream_net_indices_)->addDownstreamNode(getDriverMultiplier(drive_mult_name));
602        }
603
604        // Assign downstream_net_name_[end:begin] = driver_multiplier_name_
605        ElectricalDriverMultiplier* drive_mult = getDriverMultiplier(drive_mult_name);
606        int begin_index = downstream_net_indices_.first;
607        int end_index = downstream_net_indices_.second;
608        for(int i = begin_index; i <= end_index; ++i)
609        {
610            drive_mult->addDownstreamNode(getNet(downstream_net_name_, makeNetIndex(i)));
611        }
612        return;
613    }
614
615    void ElectricalModel::assignVirtualFanin(const String& downstream_net_name_, const String& upstream_net_name_)
616    {
617        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
618                " -> Net '" + upstream_net_name_ + "' does not exist!");
619        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
620                " -> Net '" + downstream_net_name_ + "' does not exist!");
621
622        assignVirtualFanin(downstream_net_name_, getNetReference(downstream_net_name_), upstream_net_name_, getNetReference(upstream_net_name_));
623        return;
624    }
625
626    void ElectricalModel::assignVirtualFanin(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
627    {
628        ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
629                " -> Net '" + upstream_net_name_ + "' does not exist!");
630        ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
631                " -> Net '" + downstream_net_name_ + "' does not exist!");
632
633        int begin_index = upstream_net_indices_.first;
634        int end_index = upstream_net_indices_.second;
635
636        for(int i = begin_index; i <= end_index; ++i)
637        {
638            getNet(upstream_net_name_, makeNetIndex(i))->addDownstreamNode(getNet(downstream_net_name_, downstream_net_indices_));
639        }
640        return;
641    }
642
643    void ElectricalModel::createElectricalResults()
644    {
645        // Add active area result
646        addAreaResult(new Result("Active"));
647
648        // Add wire area result
649        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
650        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
651        TechModel::ConstWireLayerIterator it;
652        for(it = it_begin; it != it_end; ++it)
653        {
654            const String& layer_name = (*it);
655            addAreaResult(new Result(layer_name + "Wire"));
656        }
657
658        // Add leakage result
659        addNddPowerResult(new Result("Leakage"));
660
661        // Add idle event result
662        createElectricalEventResult("Idle");
663        return;
664    }
665
666    void ElectricalModel::addElectricalSubResults(const ElectricalModel* model_, double number_models_)
667    {
668        // Add active area sub result
669        getAreaResult("Active")->addSubResult(model_->getAreaResult("Active"), model_->getInstanceName(), number_models_);
670
671        // Add wire area sub result
672        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
673        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
674        TechModel::ConstWireLayerIterator it;
675        for(it = it_begin; it != it_end; ++it)
676        {
677            const String& layer_name = (*it);
678            const String& result_name = layer_name + "Wire";
679            getAreaResult(result_name)->addSubResult(model_->getAreaResult(result_name), model_->getInstanceName(), number_models_);
680        }
681
682        // Add leakage sub result
683        getNddPowerResult("Leakage")->addSubResult(model_->getNddPowerResult("Leakage"), model_->getInstanceName(), number_models_);
684
685        // Add idle event sub result
686        getEventResult("Idle")->addSubResult(model_->getEventResult("Idle"), model_->getInstanceName(), number_models_);
687        return;
688    }
689
690    void ElectricalModel::addElectricalWireSubResult(const String& wire_layer_, const Result* result_, const String& producer_, double number_results_)
691    {
692        getAreaResult(wire_layer_ + "Wire")->addSubResult(result_, producer_, number_results_);
693        return;
694    }
695
696    void ElectricalModel::createElectricalAtomicResults()
697    {
698        // Add active area result
699        addAreaResult(new AtomicResult("Active"));
700
701        // Add wire area result
702        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
703        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
704        TechModel::ConstWireLayerIterator it;
705        for(it = it_begin; it != it_end; ++it)
706        {
707            const String& layer_name = (*it);
708            addAreaResult(new AtomicResult(layer_name + "Wire"));
709        }
710
711        // Add leakage result
712        addNddPowerResult(new AtomicResult("Leakage"));
713
714        // Add idle event result
715        createElectricalEventAtomicResult("Idle");
716        return;
717    }
718
719    void ElectricalModel::addElecticalAtomicResultValues(const ElectricalModel* model_, double number_models_)
720    {
721        getAreaResult("Active")->addValue(model_->getAreaResult("Active")->calculateSum() * number_models_);
722
723        // Add wire area sub result
724        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
725        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
726        TechModel::ConstWireLayerIterator it;
727        for(it = it_begin; it != it_end; ++it)
728        {
729            const String& layer_name = (*it);
730            const String& result_name = layer_name + "Wire";
731            getAreaResult(result_name)->addValue(model_->getAreaResult(result_name)->calculateSum() * number_models_);
732        }
733
734        // Add leakage sub result
735        getNddPowerResult("Leakage")->addValue(model_->getNddPowerResult("Leakage")->calculateSum() * number_models_);
736
737        // Add idle event sub result
738        getEventResult("Idle")->addValue(model_->getEventResult("Idle")->calculateSum() * number_models_);
739        return;
740    }
741
742    void ElectricalModel::addElecticalWireAtomicResultValue(const String& wire_layer_, double value_)
743    {
744        getAreaResult(wire_layer_ + "Wire")->addValue(value_);
745        return;
746    }
747
748    void ElectricalModel::resetElectricalAtomicResults()
749    {
750        getAreaResult("Active")->setValue(0.0);
751
752        // Reset wire area sub result
753        TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
754        TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
755        TechModel::ConstWireLayerIterator it;
756        for(it = it_begin; it != it_end; ++it)
757        {
758            const String& layer_name = (*it);
759            const String& result_name = layer_name + "Wire";
760            getAreaResult(result_name)->setValue(0.0);
761        }
762
763        // Reset leakage sub result
764        getNddPowerResult("Leakage")->setValue(0.0);
765
766        // Reset idle event sub result
767        getEventResult("Idle")->setValue(0.0);
768
769        return;
770    }
771
772    void ElectricalModel::createElectricalEventResult(const String& name_)
773    {
774        // Add the event result
775        addEventResult(new Result(name_));
776        // Add event info
777        m_event_infos_->set(name_, new EventInfo(name_, getInputs()));
778        return;
779    }
780
781    void ElectricalModel::createElectricalEventAtomicResult(const String& name_)
782    {
783        // Add the event result
784        addEventResult(new AtomicResult(name_));
785        // Add event info
786        m_event_infos_->set(name_, new EventInfo(name_, getInputs()));
787        return;
788    }
789
790    void ElectricalModel::assignPortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const TransitionInfo& trans_info_)
791    {
792        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
793                " -> Downstream model does not exist");
794
795        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info_);
796        return;
797    }
798
799    void ElectricalModel::propagatePortTransitionInfo(const String& downstream_port_name_, const String& upstream_port_name_)
800    {
801        const TransitionInfo& trans_info = getInputPort(upstream_port_name_)->getTransitionInfo();
802        getOutputPort(downstream_port_name_)->setTransitionInfo(trans_info);
803        return;
804    }
805
806    void ElectricalModel::propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const String& upstream_port_name_)
807    {
808        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
809                " -> Downstream model does not exist");
810
811        const TransitionInfo& trans_info = getInputPort(upstream_port_name_)->getTransitionInfo();
812        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info);
813        return;
814    }
815
816    void ElectricalModel::propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_)
817    {
818        ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
819                " -> Downstream model does not exist");
820        ASSERT(upstream_model_ != NULL, "[Error] " + getInstanceName() +
821                " -> Upstream model does not exist");
822
823        const TransitionInfo& trans_info = upstream_model_->getOutputPort(upstream_port_name_)->getTransitionInfo();
824
825        downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info);
826        return;
827    }
828
829    void ElectricalModel::propagatePortTransitionInfo(const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_)
830    {
831        ASSERT(upstream_model_ != NULL, "[Error] " + getInstanceName() +
832                " -> Upstream model does not exist");
833
834        const TransitionInfo& trans_info = upstream_model_->getOutputPort(upstream_port_name_)->getTransitionInfo();
835        getOutputPort(downstream_port_name_)->setTransitionInfo(trans_info);
836        return;
837    }
838
839    void ElectricalModel::propagateTransitionInfo()
840    {
841        // by default do nothing.
842    }
843
844    void ElectricalModel::useModel(const String& event_name_)
845    {
846        getGenProperties()->set("UseModelEvent", event_name_);
847        applyTransitionInfo(event_name_);
848        useModel();
849        return;
850    }
851
852    void ElectricalModel::useModel()
853    {
854        propagateTransitionInfo();
855        return;
856    }
857
858    void ElectricalModel::applyTransitionInfo(const String& event_name_)
859    {
860        // Check if the event actually exists
861        ASSERT(hasEventResult(event_name_), "[Error] " + getInstanceName() +
862                " -> Event (" + event_name_ + ") does not exist in the result map");
863        ASSERT(m_event_infos_->keyExist(event_name_), "[Error] " + getInstanceName() +
864                " -> Event (" + event_name_ + ") does not exist in the event info map");
865
866        const EventInfo* event_info = m_event_infos_->get(event_name_);
867
868        // Set the input ports' transition information for the event
869        Map<PortInfo*>::ConstIterator it_begin = m_input_ports_->begin();
870        Map<PortInfo*>::ConstIterator it_end = m_input_ports_->end();
871        Map<PortInfo*>::ConstIterator it;
872        for(it = it_begin; it != it_end; ++it)
873        {
874            const String& port_name = it->first;
875            PortInfo* port_info = it->second;
876            const TransitionInfo& trans_info = event_info->getTransitionInfo(port_name);
877            port_info->setTransitionInfo(trans_info);
878        }
879
880        return;
881    }
882
883    EventInfo* ElectricalModel::getEventInfo(const String& event_name_)
884    {
885        ASSERT(m_event_infos_->keyExist(event_name_), "[Error] " + getInstanceName() +
886                " -> Event (" + event_name_ + ") does not exist");
887
888        return m_event_infos_->get(event_name_);
889    }
890
891} // namespace DSENT
892
893