diff options
Diffstat (limited to 'ext/dsent/model/ElectricalModel.cc')
-rw-r--r-- | ext/dsent/model/ElectricalModel.cc | 871 |
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 + |