blob: f85a7cb97b0b4f6792701208be157d83004b2b1d [file] [log] [blame]
/* 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.
*/
#ifndef __DSENT_MODEL_ELECTRICALMODEL_H__
#define __DSENT_MODEL_ELECTRICALMODEL_H__
#include "util/CommonType.h"
#include "model/Model.h"
#include "model/TransitionInfo.h"
namespace DSENT
{
class PortInfo;
class EventInfo;
class ElectricalDriver;
class ElectricalDriverMultiplier;
class ElectricalNet;
class ElectricalLoad;
class ElectricalDelay;
// A Net index consisting of a start and end index
typedef std::pair<int, int> NetIndex;
// Helper function to make net index
inline NetIndex makeNetIndex(int start_index_, int end_index_)
{
ASSERT((end_index_ >= start_index_), (String)"[Error] Invalid net index range " +
"[" + (String)start_index_ + ":" + (String)end_index_ + "]");
return NetIndex(start_index_, end_index_);
}
// Helper function to make net index
inline NetIndex makeNetIndex(int index_)
{
return makeNetIndex(index_, index_);
}
// Helper function to trun NetIndex to String
inline String toString(const NetIndex& net_index_)
{
return "[" + String(net_index_.second) + ":" + String(net_index_.first) + "]";
}
// ElectricalModel specifies physical connectivity to other models as well as the port
// parameters for the current model
class ElectricalModel : public Model
{
public:
ElectricalModel(const String& instance_name_, const TechModel* tech_model_);
virtual ~ElectricalModel();
public:
// Check if all properties needed exist in the m_properties_
virtual void checkProperties() const;
// Set available driving strength vector from string
void setAvailableDrivingStrengths(const String& driving_strengths_);
//-----------------------------------------------------------------
// Connectivity specification
//-----------------------------------------------------------------
// Net Indices
const Map<NetIndex>* getNetReferences() const;
const NetIndex getNetReference(const String& name_) const;
// Input Ports
void createInputPort(const String& name_, const NetIndex& net_indices_ = NetIndex(0, 0));
const Map<PortInfo*>* getInputs() const;
PortInfo* getInputPort(const String& name_);
const PortInfo* getInputPort(const String& name_) const;
// Output Ports
void createOutputPort(const String& name_, const NetIndex& net_indices_ = NetIndex(0, 0));
const Map<PortInfo*>* getOutputs() const;
PortInfo* getOutputPort(const String& name_);
const PortInfo* getOutputPort(const String& name_) const;
// Electrical Nets
void createNet(const String& name_);
void createNet(const String& name_, const NetIndex& net_indices_);
const Map<ElectricalNet*>* getNets() const;
ElectricalNet* getNet(const String& name_);
ElectricalNet* getNet(const String& name_, const NetIndex& index_);
// Assign a net to be downstream from another net
// case 1: 'assign downstream_net_name_ = upstream_net_name_'
void assign(const String& downstream_net_name_, const String& upstream_net_name_);
// case 2: 'assign downstream_net_name_[end:begin] = upstream_net_name_'
void assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_);
// case 3: 'assign downstream_net_name_ = upstream_net_name_[end:begin]'
void assign(const String& downstream_net_name_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_);
// case 4: 'assign downstream_net_name_[end:begin] = upstream_net_name_[end:begin]'
void assign(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_);
// Connect a port (input or output) to some ElectricalNet
// case 1: .connect_port_name_(connect_net_name_)
void portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_);
// case 2: .connect_port_name_(connect_net_name[end:begin])
void portConnect(ElectricalModel* connect_model_, const String& connect_port_name_, const String& connect_net_name_, const NetIndex& connect_net_indices_);
// Assign a net to be downstream from another net through a driver multipliers
void assignVirtualFanout(const String& downstream_net_name_, const String& upstream_net_name_);
void assignVirtualFanout(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_);
// Assign a net to be downstream from another net
// This is used to enable bit_duplication
void assignVirtualFanin(const String& downstream_net_name_, const String& upstream_net_name_);
void assignVirtualFanin(const String& downstream_net_name_, const NetIndex& downstream_net_indices_, const String& upstream_net_name_, const NetIndex& upstream_net_indices_);
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Timing Model Components
//-----------------------------------------------------------------
// Electrical Drivers
void createDriver(const String& name_, bool sizable_);
//void createDriver(const String& name_, bool sizable_, int start_index_, int end_index_);
const Map<ElectricalDriver*>* getDrivers() const;
ElectricalDriver* getDriver(const String& name_);
// Electrical Driver Multipliers
void createDriverMultiplier(const String& name_);
const Map<ElectricalDriverMultiplier*>* getDriverMultipliers() const;
ElectricalDriverMultiplier* getDriverMultiplier(const String& name_);
// Electrical Loads
void createLoad(const String& name_);
//void createLoad(const String& name_, int start_index_, int end_index_);
const Map<ElectricalLoad*>* getLoads() const;
ElectricalLoad* getLoad(const String& name_);
// Electrical Delay creation
void createDelay(const String& name_);
//void createDelay(const String& name_, int start_index_, int end_index_);
const Map<ElectricalDelay*>* getDelays() const;
ElectricalDelay* getDelay(const String& name_);
//-----------------------------------------------------------------
// Get current driving strength
double getDrivingStrength() const;
// Get current driving strength index
int getDrivingStrengthIdx() const;
// Set driving strength by index
void setDrivingStrengthIdx(int idx_);
// Set the instance to minimum driving strength
void setMinDrivingStrength();
// Return true if the instance has minimum driving strength
bool hasMinDrivingStrength() const;
// Return true if the instance has maximum driving strength
bool hasMaxDrivingStrength() const;
// Increase driving strength index by 1
void increaseDrivingStrength();
// Decrease driving strength index by 1
void decreaseDrivingStrength();
// Create the default sets of the electrical results
void createElectricalResults();
// Add the default sets of the electrical results from a model
void addElectricalSubResults(const ElectricalModel* model_, double number_models_);
// Add extra wire sub results
void addElectricalWireSubResult(const String& wire_layer_, const Result* result_, const String& producer_, double number_results_);
// Create the default sets of the electrical atomic results
void createElectricalAtomicResults();
// Accumulate the electrical atomic results' values
void addElecticalAtomicResultValues(const ElectricalModel* model_, double number_models_);
// Add extra wire sub results
void addElecticalWireAtomicResultValue(const String& wire_layer_, double value_);
// Reset the electrical atomic results' values
void resetElectricalAtomicResults();
// Create an electrical event result. This will add an event associate to all input/output ports
void createElectricalEventResult(const String& name_);
// Create an electrical event atomic result
void createElectricalEventAtomicResult(const String& name_);
//-----------------------------------------------------------------
// Helper functions to propagate transition information
//-----------------------------------------------------------------
void assignPortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const TransitionInfo& trans_info_);
void propagatePortTransitionInfo(const String& downstream_port_name_, const String& upstream_port_name_);
void propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const String& upstream_port_name_);
void propagatePortTransitionInfo(ElectricalModel* downstream_model_, const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_);
void propagatePortTransitionInfo(const String& downstream_port_name_, const ElectricalModel* upstream_model_, const String& upstream_port_name_);
virtual void propagateTransitionInfo();
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Helper functions to insert and remove buffers
//-----------------------------------------------------------------
//-----------------------------------------------------------------
virtual void useModel(const String& event_name_);
virtual void useModel();
// TODO - add comments
void applyTransitionInfo(const String& event_name_);
// TODO - add comments
EventInfo* getEventInfo(const String& event_name_);
protected:
// In an ElectricalModel, the complete port-to-port connectivity
// of all sub-instance must be specified. Addition/Removal ports or
// port-related nets cannot happen after this step
//virtual void constructModel() = 0;
// In an ElectricalModel, updateModel MUST finish all necessary
// calculations such that a timing model can be run
//virtual void updateModel() = 0;
// In an ElectricalModel, evaluateModel should calculate all
// event energies, now that the connectivity and timing has been
// completed
//virtual void evaluateModel() = 0;
private:
// Private copy constructor. Use clone to perform copy operation.
ElectricalModel(const ElectricalModel& model_);
private:
// Contains the driving strengths in increasing order
vector<double> m_driving_strengths_;
// Driving strength index in the driving strength vector
int m_curr_driving_strengths_idx_;
//Connectivity elements
// Nets can come in various bus widths. A net reference is really
// just a helper map mapping a referenced map name to a bunch of
// net indices. A net index returns the starting and end indices of
// a net if the net is a multi-bit bus of some sort
Map<NetIndex>* m_net_references_;
// Map of the input ports
Map<PortInfo*>* m_input_ports_;
// Map of the output ports
Map<PortInfo*>* m_output_ports_;
// Map of all our electrical nets
Map<ElectricalNet*>* m_nets_;
//Timing model elements
// Map of all our electrical drivers
Map<ElectricalDriver*>* m_drivers_;
// Map of all our driver multipliers
Map<ElectricalDriverMultiplier*>* m_driver_multipliers_;
// Map of all our electrical loads
Map<ElectricalLoad*>* m_loads_;
// Map of all our idealized delays
Map<ElectricalDelay*>* m_delays_;
// Map of the event infos
Map<EventInfo*>* m_event_infos_;
}; // class ElectricalModel
} // namespace DSENT
#endif // __DSENT_MODEL_ELECTRICALMODEL_H__