summaryrefslogtreecommitdiff
path: root/ext/dsent/model/ElectricalModel.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dsent/model/ElectricalModel.cc')
-rw-r--r--ext/dsent/model/ElectricalModel.cc871
1 files changed, 871 insertions, 0 deletions
diff --git a/ext/dsent/model/ElectricalModel.cc b/ext/dsent/model/ElectricalModel.cc
new file mode 100644
index 000000000..469e26c9e
--- /dev/null
+++ b/ext/dsent/model/ElectricalModel.cc
@@ -0,0 +1,871 @@
+#include "model/ElectricalModel.h"
+
+#include "model/PortInfo.h"
+#include "model/EventInfo.h"
+#include "model/timing_graph/ElectricalDriver.h"
+#include "model/timing_graph/ElectricalDriverMultiplier.h"
+#include "model/timing_graph/ElectricalNet.h"
+#include "model/timing_graph/ElectricalLoad.h"
+#include "model/timing_graph/ElectricalDelay.h"
+
+namespace DSENT
+{
+ ElectricalModel::ElectricalModel(const String& instance_name_, const TechModel* tech_model_)
+ : Model(instance_name_, tech_model_)
+ {
+ m_curr_driving_strengths_idx_ = -1;
+ m_input_ports_ = new Map<PortInfo*>;
+ m_output_ports_ = new Map<PortInfo*>;
+ m_net_references_ = new Map<NetIndex>;
+ m_drivers_ = new Map<ElectricalDriver*>;
+ m_driver_multipliers_ = new Map<ElectricalDriverMultiplier*>;
+ m_nets_ = new Map<ElectricalNet*>;
+ m_loads_ = new Map<ElectricalLoad*>;
+ m_delays_ = new Map<ElectricalDelay*>;
+ m_event_infos_ = new Map<EventInfo*>;
+ }
+
+ ElectricalModel::~ElectricalModel()
+ {
+ deletePtrMap<PortInfo>(m_input_ports_);
+ deletePtrMap<PortInfo>(m_output_ports_);
+ delete m_net_references_;
+ deletePtrMap<ElectricalDriver>(m_drivers_);
+ deletePtrMap<ElectricalDriverMultiplier>(m_driver_multipliers_);
+ deletePtrMap<ElectricalNet>(m_nets_);
+ deletePtrMap<ElectricalLoad>(m_loads_);
+ deletePtrMap<ElectricalDelay>(m_delays_);
+ deletePtrMap<EventInfo>(m_event_infos_);
+ m_input_ports_ = NULL;
+ m_output_ports_ = NULL;
+ m_net_references_ = NULL;
+ m_drivers_ = NULL;
+ m_driver_multipliers_ = NULL;
+ m_nets_ = NULL;
+ m_loads_ = NULL;
+ m_net_references_ = NULL;
+ m_event_infos_ = NULL;
+ }
+
+ void ElectricalModel::checkProperties() const
+ {
+ // Check if the specified driving strength exists in the available driving strengths
+ if(getProperties()->keyExist("DrivingStrength"))
+ {
+ const double driving_strength = getProperty("DrivingStrength");
+ bool is_found = false;
+ for(int i = 0; i < (int)m_driving_strengths_.size(); ++i)
+ {
+ if(driving_strength == m_driving_strengths_[i])
+ {
+ is_found = true;
+ break;
+ }
+ }
+ ASSERT(is_found, "[Error] " + getInstanceName() +
+ " -> Driving strength (" + String(driving_strength) + ")"
+ " not found in available driving strengths (" +
+ getParameter("AvailableDrivingStrengths"));
+ }
+
+ // Do normal check on the properties
+ Model::checkProperties();
+ return;
+ }
+
+ double ElectricalModel::getDrivingStrength() const
+ {
+ if(m_curr_driving_strengths_idx_ == -1)
+ {
+ return 0;
+ }
+ else
+ {
+ return m_driving_strengths_[m_curr_driving_strengths_idx_];
+ }
+ }
+
+ int ElectricalModel::getDrivingStrengthIdx() const
+ {
+ return m_curr_driving_strengths_idx_;
+ }
+
+ void ElectricalModel::setDrivingStrengthIdx(int idx_)
+ {
+ ASSERT(((idx_ >= 0) && (idx_ < (int)m_driving_strengths_.size())),
+ "[Error] " + getInstanceName() +
+ " -> Driving strength index out of range (" + String(idx_) + ")");
+
+ m_curr_driving_strengths_idx_ = idx_;
+ setProperty("DrivingStrength", m_driving_strengths_[m_curr_driving_strengths_idx_]);
+
+ Log::printLine(getInstanceName() + " -> Changing drive strength to " + (String) m_driving_strengths_[m_curr_driving_strengths_idx_]);
+ update();
+ return;
+ }
+
+ void ElectricalModel::setMinDrivingStrength()
+ {
+ setDrivingStrengthIdx(0);
+ return;
+ }
+
+ bool ElectricalModel::hasMinDrivingStrength() const
+ {
+ return (m_curr_driving_strengths_idx_ == 0);
+ }
+
+ bool ElectricalModel::hasMaxDrivingStrength() const
+ {
+ return (m_curr_driving_strengths_idx_ == ((int)m_driving_strengths_.size() - 1));
+ }
+
+ void ElectricalModel::increaseDrivingStrength()
+ {
+ if(!hasMaxDrivingStrength())
+ {
+ setDrivingStrengthIdx(m_curr_driving_strengths_idx_ + 1);
+ }
+ return;
+ }
+
+ void ElectricalModel::decreaseDrivingStrength()
+ {
+ if(!hasMinDrivingStrength())
+ {
+ setDrivingStrengthIdx(m_curr_driving_strengths_idx_ - 1);
+ }
+ return;
+ }
+
+ void ElectricalModel::setAvailableDrivingStrengths(const String& driving_strengths_)
+ {
+ setParameter("AvailableDrivingStrengths", driving_strengths_);
+ const vector<String>& split_str = driving_strengths_.split("[,");
+
+ // Check if there is at least one driving strength specified
+ ASSERT(!split_str.empty(), "[Error] " + getInstanceName() +
+ " -> Specified driving strength string does not contain any driving strengths (" +
+ driving_strengths_ + ")");
+
+ // TODO - check if the driving strengths is sorted
+
+ // Overwrite the available driving strengths
+ m_driving_strengths_.clear();
+ for(int i = 0; i < (int)split_str.size(); ++i)
+ {
+ m_driving_strengths_.push_back(split_str[i].toDouble());
+ }
+
+ // Set the driving strength to minimum
+ m_curr_driving_strengths_idx_ = 0;
+ setProperty("DrivingStrength", m_driving_strengths_[m_curr_driving_strengths_idx_]);
+ return;
+ }
+
+ // Connect a port (input or output) to some ElectricalNet
+ void ElectricalModel::portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_)
+ {
+ ASSERT(m_net_references_->keyExist(connect_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + connect_net_name_ + "' does not exist!");
+
+ portConnect(connect_model_, connect_port_name_, connect_net_name_, m_net_references_->get(connect_net_name_));
+ }
+
+ void ElectricalModel::portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_, const NetIndex& connect_net_indices_)
+ {
+ ASSERT(m_net_references_->keyExist(connect_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + connect_net_name_ + "' does not exist!");
+
+ // Check whether the port name is an input or output, ASSERTion error if neither
+ bool is_input = connect_model_->getInputs()->keyExist(connect_port_name_);
+ bool is_output = connect_model_->getOutputs()->keyExist(connect_port_name_);
+
+ ASSERT(is_input || is_output, "[Error] " + getInstanceName() + " -> Model '" + connect_model_->getInstanceName() +
+ "' does not have a port named '" + connect_port_name_ + "'!");
+
+ int connect_net_width = connect_net_indices_.second - connect_net_indices_.first + 1;
+ const NetIndex& port_indices = connect_model_->getNetReference(connect_port_name_);
+ int port_width = port_indices.second - port_indices.first + 1;
+
+ ASSERT(connect_net_width == port_width, "[Error] " + getInstanceName() + " -> Port width mismatch for Model '" +
+ connect_model_->getInstanceName() + "." + connect_port_name_ + toString(port_indices) +
+ "' and net '" + connect_net_name_ + toString(connect_net_indices_) + "'!");
+
+ int port_index = port_indices.first;
+ int connect_net_index = connect_net_indices_.first;
+
+ if(is_input)
+ {
+ while(port_index <= port_indices.second)
+ {
+ getNet(connect_net_name_, makeNetIndex(connect_net_index))->addDownstreamNode(
+ connect_model_->getNet(connect_port_name_, makeNetIndex(port_index)));
+ ++port_index;
+ ++connect_net_index;
+ }
+ }
+ else if(is_output)
+ {
+ while (port_index <= port_indices.second)
+ {
+ connect_model_->getNet(connect_port_name_, makeNetIndex(port_index))->addDownstreamNode(
+ getNet(connect_net_name_, makeNetIndex(connect_net_index)));
+ ++port_index;
+ ++connect_net_index;
+ }
+ }
+ }
+
+ //Get Drivers
+ const Map<ElectricalDriver*>* ElectricalModel::getDrivers() const
+ {
+ return m_drivers_;
+ }
+
+ ElectricalDriver* ElectricalModel::getDriver(const String& name_)
+ {
+ return m_drivers_->get(name_);
+ }
+
+ //Get Driver Multipliers
+ const Map<ElectricalDriverMultiplier*>* ElectricalModel::getDriverMultipliers() const
+ {
+ return m_driver_multipliers_;
+ }
+
+ ElectricalDriverMultiplier* ElectricalModel::getDriverMultiplier(const String& name_)
+ {
+ return m_driver_multipliers_->get(name_);
+ }
+
+ //Get Nets
+ const Map<ElectricalNet*>* ElectricalModel::getNets() const
+ {
+ return m_nets_;
+ }
+
+ ElectricalNet* ElectricalModel::getNet(const String& name_)
+ {
+ return getNet(name_, m_net_references_->get(name_));
+ }
+
+ ElectricalNet* ElectricalModel::getNet(const String& name_, const NetIndex& index_)
+ {
+ ASSERT(index_.first == index_.second, "[Error] " + getInstanceName() +
+ " -> Ambiguous get net since (" + name_ + ") is a bus consisting of several nets!");
+ return m_nets_->get(name_ + "[" + (String) index_.first + "]");
+ }
+
+ //Get Loads
+ const Map<ElectricalLoad*>* ElectricalModel::getLoads() const
+ {
+ return m_loads_;
+ }
+
+ ElectricalLoad* ElectricalModel::getLoad(const String& name_)
+ {
+ return m_loads_->get(name_);
+ }
+
+ //Get Delays
+ const Map<ElectricalDelay*>* ElectricalModel::getDelays() const
+ {
+ return m_delays_;
+ }
+
+ ElectricalDelay* ElectricalModel::getDelay(const String& name_)
+ {
+ return m_delays_->get(name_);
+ }
+
+ //Get Inputs
+ const Map<PortInfo*>* ElectricalModel::getInputs() const
+ {
+ return m_input_ports_;
+ }
+
+ PortInfo* ElectricalModel::getInputPort(const String& name_)
+ {
+ ASSERT(m_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
+ " -> Input port (" + name_ + ") does not exist");
+
+ return m_input_ports_->get(name_);
+ }
+
+ const PortInfo* ElectricalModel::getInputPort(const String& name_) const
+ {
+ ASSERT(m_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
+ " -> Input port (" + name_ + ") does not exist");
+
+ return m_input_ports_->get(name_);
+ }
+
+ //Get Outputs
+ const Map<PortInfo*>* ElectricalModel::getOutputs() const
+ {
+ return m_output_ports_;
+ }
+
+ PortInfo* ElectricalModel::getOutputPort(const String& name_)
+ {
+ ASSERT(m_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
+ " -> Output port (" + name_ + ") does not exist");
+
+ return m_output_ports_->get(name_);
+ }
+
+ const PortInfo* ElectricalModel::getOutputPort(const String& name_) const
+ {
+ ASSERT(m_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
+ " -> Output port (" + name_ + ") does not exist");
+
+ return m_output_ports_->get(name_);
+ }
+
+ const Map<NetIndex>* ElectricalModel::getNetReferences() const
+ {
+ return m_net_references_;
+ }
+
+ const NetIndex ElectricalModel::getNetReference(const String& name_) const
+ {
+ return m_net_references_->get(name_);
+ }
+
+ //-------------------------------------------------------------------------
+ // Electrical Connectivity and Timing Element Creation Functions
+ //-------------------------------------------------------------------------
+
+ // Input Port creation
+ void ElectricalModel::createInputPort(const String& name_, const NetIndex& net_indices_)
+ {
+ // Create the new nets (including its net reference)
+ // This should already check that it has not been previously declared
+ createNet(name_, net_indices_);
+ // Add the net name to list of input ports
+ m_input_ports_->set(name_, new PortInfo(name_, net_indices_));
+ return;
+ }
+
+ // Output Port creation
+ void ElectricalModel::createOutputPort(const String& name_, const NetIndex& net_indices_)
+ {
+ // Create the new nets (including its net reference)
+ // This should already check that it has not been previously declared
+ createNet(name_, net_indices_);
+ // Add the net name to list of output ports
+ m_output_ports_->set(name_, new PortInfo(name_, net_indices_));
+ return;
+ }
+
+ // Net creation
+ void ElectricalModel::createNet(const String& name_)
+ {
+ // Creating a net with specifying an index range means that the net is just
+ // a 1-bit wire indexed at [0]
+ createNet(name_, makeNetIndex(0, 0));
+ return;
+ }
+
+ void ElectricalModel::createNet(const String& name_, const NetIndex& net_indices_)
+ {
+ // Check that it hasn't been previously declared
+ ASSERT( !m_nets_->keyExist(name_) && !m_net_references_->keyExist(name_),
+ "[Error] " + getInstanceName() + " -> Redeclaration of net " + name_);
+
+ int start = net_indices_.first;
+ int end = net_indices_.second;
+
+ for (int index = start; index <= end; ++index)
+ {
+ String indexed_name = name_ + "[" + (String) index + "]";
+ // Create the new net
+ ElectricalNet* net = new ElectricalNet(indexed_name, this);
+ // Add the net to net map
+ m_nets_->set(indexed_name, net);
+ }
+ // Add net to net references
+ m_net_references_->set(name_, net_indices_);
+ return;
+ }
+
+ // Driver creation
+ void ElectricalModel::createDriver(const String& name_, bool sizable_)
+ {
+ // Check that it hasn't been previously declared
+ ASSERT( !m_drivers_->keyExist(name_),
+ "[Error] " + getInstanceName() + " -> Redeclaration of driver " + name_);
+
+ ElectricalDriver* driver = new ElectricalDriver(name_, this, sizable_);
+ m_drivers_->set(name_, driver);
+ return;
+ }
+
+ /*
+ void ElectricalModel::createDriver(const String& name_, bool sizable_, int start_index_, int end_index_)
+ {
+ for (int index = start_index_; index <= end_index_; ++index)
+ {
+ createDriver(name_ + "[" + (String) index + "]", sizable_);
+ }
+ return;
+ }
+ */
+
+ // Driver Multiplier creation
+ void ElectricalModel::createDriverMultiplier(const String& name_)
+ {
+ // Check that it hasn't been previously declared
+ ASSERT( !m_driver_multipliers_->keyExist(name_),
+ "[Error] " + getInstanceName() + " -> Redeclaration of driver_multiplier " + name_);
+
+ ElectricalDriverMultiplier* driver_multiplier = new ElectricalDriverMultiplier(name_, this);
+ m_driver_multipliers_->set(name_, driver_multiplier);
+ return;
+ }
+
+ // Load creation
+
+ void ElectricalModel::createLoad(const String& name_)
+ {
+ // Check that it hasn't been previously declared
+ ASSERT( !m_loads_->keyExist(name_),
+ "[Error] " + getInstanceName() + " -> Redeclaration of load " + name_);
+
+ ElectricalLoad* load = new ElectricalLoad(name_, this);
+ m_loads_->set(name_, load);
+ return;
+ }
+
+ /*
+ void ElectricalModel::createLoad(const String& name_, int start_index_, int end_index_)
+ {
+ for (int index = start_index_; index <= end_index_; ++index)
+ {
+ createLoad(name_ + "[" + (String) index + "]");
+ }
+ return;
+ }
+ */
+
+ // Delay creation
+ void ElectricalModel::createDelay(const String& name_)
+ {
+ // Check that it hasn't been previously declared
+ ASSERT( !m_delays_->keyExist(name_),
+ "[Error] " + getInstanceName() + " -> Redeclaration of delay " + name_);
+
+ ElectricalDelay* delay = new ElectricalDelay(name_, this);
+ m_delays_->set(name_, delay);
+ return;
+ }
+
+ /*
+ void ElectricalModel::createDelay(const String& name_, int start_index_, int end_index_)
+ {
+ for (int index = start_index_; index <= end_index_; ++index)
+ {
+ createDelay(name_ + "[" + (String) index + "]");
+ }
+ return;
+ }
+ */
+ //-------------------------------------------------------------------------
+
+ // Assign a net to be downstream from another net
+ // case 1: 'assign downstream_net_name_ = upstream_net_name_'
+ void ElectricalModel::assign(const String& downstream_net_name_, const String& upstream_net_name_)
+ {
+ ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
+ downstream_net_name_ + "' does not exist!");
+
+ ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
+ upstream_net_name_ + "' does not exist!");
+
+ assign(downstream_net_name_, getNetReference(downstream_net_name_),
+ upstream_net_name_, getNetReference(upstream_net_name_));
+
+ return;
+ }
+
+ // case 2: 'assign downstream_net_name_[begin:end] = upstream_net_name_'
+ void ElectricalModel::assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_)
+ {
+ ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
+ downstream_net_name_ + "' does not exist!");
+
+ ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
+ upstream_net_name_ + "' does not exist!");
+
+ assign(downstream_net_name_, downstream_net_indices_,
+ upstream_net_name_, getNetReference(upstream_net_name_));
+
+ return;
+ }
+
+ // case 3: 'assign downstream_net_name_ = upstream_net_name_[begin:end]'
+ void ElectricalModel::assign(const String& downstream_net_name_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
+ {
+ ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
+ downstream_net_name_ + "' does not exist!");
+
+ ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
+ upstream_net_name_ + "' does not exist!");
+
+ assign(downstream_net_name_, getNetReference(downstream_net_name_),
+ upstream_net_name_, upstream_net_indices_);
+
+ return;
+ }
+ // case 4: 'assign downstream_net_name_[begin:end] = upstream_net_name_[begin:end]'
+ void ElectricalModel::assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
+ {
+ ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
+ downstream_net_name_ + "' does not exist!");
+
+ ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() + " -> Net '" +
+ upstream_net_name_ + "' does not exist!");
+
+ // Check that the assignment widths are the same
+ int downstream_width = downstream_net_indices_.second - downstream_net_indices_.first + 1;
+ int upstream_width = upstream_net_indices_.second - upstream_net_indices_.first + 1;
+
+ ASSERT(downstream_width == upstream_width, "[Error] " + getInstanceName() + " -> Assignment width mismatch: " +
+ downstream_net_name_ + " (" + (String) downstream_width + ") and " +
+ upstream_net_name_ + " (" + (String) upstream_width + ")");
+
+ // Loop through indices and connect them together
+ int down_index = downstream_net_indices_.first;
+ int up_index = upstream_net_indices_.first;
+ while (down_index <= downstream_net_indices_.second)
+ {
+ getNet(upstream_net_name_, makeNetIndex(up_index))->addDownstreamNode(
+ getNet(downstream_net_name_, makeNetIndex(down_index)));
+
+ ++up_index;
+ ++down_index;
+ }
+
+ return;
+ }
+
+ // Assign a net to another net through a driver multiplier
+ void ElectricalModel::assignVirtualFanout(const String& downstream_net_name_, const String& upstream_net_name_)
+ {
+ ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + upstream_net_name_ + "' does not exist!");
+ ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + downstream_net_name_ + "' does not exist!");
+
+ assignVirtualFanout(downstream_net_name_, getNetReference(downstream_net_name_), upstream_net_name_, getNetReference(upstream_net_name_));
+ return;
+ }
+
+ // Assign a net to another net through a driver multiplier
+ void ElectricalModel::assignVirtualFanout(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
+ {
+ ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + upstream_net_name_ + "' does not exist!");
+ ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + downstream_net_name_ + "' does not exist!");
+
+ const String& drive_mult_name = upstream_net_name_ + "_" + (String) upstream_net_indices_.first + "_DriverMultiplier";
+ bool is_drive_mult_exist = getDriverMultipliers()->keyExist(drive_mult_name);
+
+ // Create a driver multiplier and assign it to upstream_net since it doesn't exist
+ if(!is_drive_mult_exist)
+ {
+ createDriverMultiplier(drive_mult_name);
+ getNet(upstream_net_name_, upstream_net_indices_)->addDownstreamNode(getDriverMultiplier(drive_mult_name));
+ }
+
+ // Assign downstream_net_name_[end:begin] = driver_multiplier_name_
+ ElectricalDriverMultiplier* drive_mult = getDriverMultiplier(drive_mult_name);
+ int begin_index = downstream_net_indices_.first;
+ int end_index = downstream_net_indices_.second;
+ for(int i = begin_index; i <= end_index; ++i)
+ {
+ drive_mult->addDownstreamNode(getNet(downstream_net_name_, makeNetIndex(i)));
+ }
+ return;
+ }
+
+ void ElectricalModel::assignVirtualFanin(const String& downstream_net_name_, const String& upstream_net_name_)
+ {
+ ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + upstream_net_name_ + "' does not exist!");
+ ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + downstream_net_name_ + "' does not exist!");
+
+ assignVirtualFanin(downstream_net_name_, getNetReference(downstream_net_name_), upstream_net_name_, getNetReference(upstream_net_name_));
+ return;
+ }
+
+ void ElectricalModel::assignVirtualFanin(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_)
+ {
+ ASSERT(getNetReferences()->keyExist(upstream_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + upstream_net_name_ + "' does not exist!");
+ ASSERT(getNetReferences()->keyExist(downstream_net_name_), "[Error] " + getInstanceName() +
+ " -> Net '" + downstream_net_name_ + "' does not exist!");
+
+ int begin_index = upstream_net_indices_.first;
+ int end_index = upstream_net_indices_.second;
+
+ for(int i = begin_index; i <= end_index; ++i)
+ {
+ getNet(upstream_net_name_, makeNetIndex(i))->addDownstreamNode(getNet(downstream_net_name_, downstream_net_indices_));
+ }
+ return;
+ }
+
+ void ElectricalModel::createElectricalResults()
+ {
+ // Add active area result
+ addAreaResult(new Result("Active"));
+
+ // Add wire area result
+ TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
+ TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
+ TechModel::ConstWireLayerIterator it;
+ for(it = it_begin; it != it_end; ++it)
+ {
+ const String& layer_name = (*it);
+ addAreaResult(new Result(layer_name + "Wire"));
+ }
+
+ // Add leakage result
+ addNddPowerResult(new Result("Leakage"));
+
+ // Add idle event result
+ createElectricalEventResult("Idle");
+ return;
+ }
+
+ void ElectricalModel::addElectricalSubResults(const ElectricalModel* model_, double number_models_)
+ {
+ // Add active area sub result
+ getAreaResult("Active")->addSubResult(model_->getAreaResult("Active"), model_->getInstanceName(), number_models_);
+
+ // Add wire area sub result
+ TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
+ TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
+ TechModel::ConstWireLayerIterator it;
+ for(it = it_begin; it != it_end; ++it)
+ {
+ const String& layer_name = (*it);
+ const String& result_name = layer_name + "Wire";
+ getAreaResult(result_name)->addSubResult(model_->getAreaResult(result_name), model_->getInstanceName(), number_models_);
+ }
+
+ // Add leakage sub result
+ getNddPowerResult("Leakage")->addSubResult(model_->getNddPowerResult("Leakage"), model_->getInstanceName(), number_models_);
+
+ // Add idle event sub result
+ getEventResult("Idle")->addSubResult(model_->getEventResult("Idle"), model_->getInstanceName(), number_models_);
+ return;
+ }
+
+ void ElectricalModel::addElectricalWireSubResult(const String& wire_layer_, const Result* result_, const String& producer_, double number_results_)
+ {
+ getAreaResult(wire_layer_ + "Wire")->addSubResult(result_, producer_, number_results_);
+ return;
+ }
+
+ void ElectricalModel::createElectricalAtomicResults()
+ {
+ // Add active area result
+ addAreaResult(new AtomicResult("Active"));
+
+ // Add wire area result
+ TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
+ TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
+ TechModel::ConstWireLayerIterator it;
+ for(it = it_begin; it != it_end; ++it)
+ {
+ const String& layer_name = (*it);
+ addAreaResult(new AtomicResult(layer_name + "Wire"));
+ }
+
+ // Add leakage result
+ addNddPowerResult(new AtomicResult("Leakage"));
+
+ // Add idle event result
+ createElectricalEventAtomicResult("Idle");
+ return;
+ }
+
+ void ElectricalModel::addElecticalAtomicResultValues(const ElectricalModel* model_, double number_models_)
+ {
+ getAreaResult("Active")->addValue(model_->getAreaResult("Active")->calculateSum() * number_models_);
+
+ // Add wire area sub result
+ TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
+ TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
+ TechModel::ConstWireLayerIterator it;
+ for(it = it_begin; it != it_end; ++it)
+ {
+ const String& layer_name = (*it);
+ const String& result_name = layer_name + "Wire";
+ getAreaResult(result_name)->addValue(model_->getAreaResult(result_name)->calculateSum() * number_models_);
+ }
+
+ // Add leakage sub result
+ getNddPowerResult("Leakage")->addValue(model_->getNddPowerResult("Leakage")->calculateSum() * number_models_);
+
+ // Add idle event sub result
+ getEventResult("Idle")->addValue(model_->getEventResult("Idle")->calculateSum() * number_models_);
+ return;
+ }
+
+ void ElectricalModel::addElecticalWireAtomicResultValue(const String& wire_layer_, double value_)
+ {
+ getAreaResult(wire_layer_ + "Wire")->addValue(value_);
+ return;
+ }
+
+ void ElectricalModel::resetElectricalAtomicResults()
+ {
+ getAreaResult("Active")->setValue(0.0);
+
+ // Reset wire area sub result
+ TechModel::ConstWireLayerIterator it_begin = getTechModel()->getAvailableWireLayers()->begin();
+ TechModel::ConstWireLayerIterator it_end = getTechModel()->getAvailableWireLayers()->end();
+ TechModel::ConstWireLayerIterator it;
+ for(it = it_begin; it != it_end; ++it)
+ {
+ const String& layer_name = (*it);
+ const String& result_name = layer_name + "Wire";
+ getAreaResult(result_name)->setValue(0.0);
+ }
+
+ // Reset leakage sub result
+ getNddPowerResult("Leakage")->setValue(0.0);
+
+ // Reset idle event sub result
+ getEventResult("Idle")->setValue(0.0);
+
+ return;
+ }
+
+ void ElectricalModel::createElectricalEventResult(const String& name_)
+ {
+ // Add the event result
+ addEventResult(new Result(name_));
+ // Add event info
+ m_event_infos_->set(name_, new EventInfo(name_, getInputs()));
+ return;
+ }
+
+ void ElectricalModel::createElectricalEventAtomicResult(const String& name_)
+ {
+ // Add the event result
+ addEventResult(new AtomicResult(name_));
+ // Add event info
+ m_event_infos_->set(name_, new EventInfo(name_, getInputs()));
+ return;
+ }
+
+ void ElectricalModel::assignPortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const TransitionInfo& trans_info_)
+ {
+ ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
+ " -> Downstream model does not exist");
+
+ downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info_);
+ return;
+ }
+
+ void ElectricalModel::propagatePortTransitionInfo(const String& downstream_port_name_, const String& upstream_port_name_)
+ {
+ const TransitionInfo& trans_info = getInputPort(upstream_port_name_)->getTransitionInfo();
+ getOutputPort(downstream_port_name_)->setTransitionInfo(trans_info);
+ return;
+ }
+
+ void ElectricalModel::propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const String& upstream_port_name_)
+ {
+ ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
+ " -> Downstream model does not exist");
+
+ const TransitionInfo& trans_info = getInputPort(upstream_port_name_)->getTransitionInfo();
+ downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info);
+ return;
+ }
+
+ void ElectricalModel::propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_)
+ {
+ ASSERT(downstream_model_ != NULL, "[Error] " + getInstanceName() +
+ " -> Downstream model does not exist");
+ ASSERT(upstream_model_ != NULL, "[Error] " + getInstanceName() +
+ " -> Upstream model does not exist");
+
+ const TransitionInfo& trans_info = upstream_model_->getOutputPort(upstream_port_name_)->getTransitionInfo();
+
+ downstream_model_->getInputPort(downstream_port_name_)->setTransitionInfo(trans_info);
+ return;
+ }
+
+ void ElectricalModel::propagatePortTransitionInfo(const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_)
+ {
+ ASSERT(upstream_model_ != NULL, "[Error] " + getInstanceName() +
+ " -> Upstream model does not exist");
+
+ const TransitionInfo& trans_info = upstream_model_->getOutputPort(upstream_port_name_)->getTransitionInfo();
+ getOutputPort(downstream_port_name_)->setTransitionInfo(trans_info);
+ return;
+ }
+
+ void ElectricalModel::propagateTransitionInfo()
+ {
+ // by default do nothing.
+ }
+
+ void ElectricalModel::useModel(const String& event_name_)
+ {
+ getGenProperties()->set("UseModelEvent", event_name_);
+ applyTransitionInfo(event_name_);
+ useModel();
+ return;
+ }
+
+ void ElectricalModel::useModel()
+ {
+ propagateTransitionInfo();
+ return;
+ }
+
+ void ElectricalModel::applyTransitionInfo(const String& event_name_)
+ {
+ // Check if the event actually exists
+ ASSERT(hasEventResult(event_name_), "[Error] " + getInstanceName() +
+ " -> Event (" + event_name_ + ") does not exist in the result map");
+ ASSERT(m_event_infos_->keyExist(event_name_), "[Error] " + getInstanceName() +
+ " -> Event (" + event_name_ + ") does not exist in the event info map");
+
+ const EventInfo* event_info = m_event_infos_->get(event_name_);
+
+ // Set the input ports' transition information for the event
+ Map<PortInfo*>::ConstIterator it_begin = m_input_ports_->begin();
+ Map<PortInfo*>::ConstIterator it_end = m_input_ports_->end();
+ Map<PortInfo*>::ConstIterator it;
+ for(it = it_begin; it != it_end; ++it)
+ {
+ const String& port_name = it->first;
+ PortInfo* port_info = it->second;
+ const TransitionInfo& trans_info = event_info->getTransitionInfo(port_name);
+ port_info->setTransitionInfo(trans_info);
+ }
+
+ return;
+ }
+
+ EventInfo* ElectricalModel::getEventInfo(const String& event_name_)
+ {
+ ASSERT(m_event_infos_->keyExist(event_name_), "[Error] " + getInstanceName() +
+ " -> Event (" + event_name_ + ") does not exist");
+
+ return m_event_infos_->get(event_name_);
+ }
+
+} // namespace DSENT
+