/* Copyright (c) 2012 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #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; m_output_ports_ = new Map; m_net_references_ = new Map; m_drivers_ = new Map; m_driver_multipliers_ = new Map; m_nets_ = new Map; m_loads_ = new Map; m_delays_ = new Map; m_event_infos_ = new Map; } ElectricalModel::~ElectricalModel() { deletePtrMap(m_input_ports_); deletePtrMap(m_output_ports_); delete m_net_references_; deletePtrMap(m_drivers_); deletePtrMap(m_driver_multipliers_); deletePtrMap(m_nets_); deletePtrMap(m_loads_); deletePtrMap(m_delays_); deletePtrMap(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& 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* ElectricalModel::getDrivers() const { return m_drivers_; } ElectricalDriver* ElectricalModel::getDriver(const String& name_) { return m_drivers_->get(name_); } //Get Driver Multipliers const Map* ElectricalModel::getDriverMultipliers() const { return m_driver_multipliers_; } ElectricalDriverMultiplier* ElectricalModel::getDriverMultiplier(const String& name_) { return m_driver_multipliers_->get(name_); } //Get Nets const Map* 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* ElectricalModel::getLoads() const { return m_loads_; } ElectricalLoad* ElectricalModel::getLoad(const String& name_) { return m_loads_->get(name_); } //Get Delays const Map* ElectricalModel::getDelays() const { return m_delays_; } ElectricalDelay* ElectricalModel::getDelay(const String& name_) { return m_delays_->get(name_); } //Get Inputs const Map* 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* 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* 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::ConstIterator it_begin = m_input_ports_->begin(); Map::ConstIterator it_end = m_input_ports_->end(); Map::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