c1aecc05e6
This patch extensively modifies DSENT so that it can be accessed using Python. To access the Python interface, DSENT needs to compiled as a shared library. For this purpose a CMakeLists.txt file has been added. Some of the code that is not required is being removed.
237 lines
10 KiB
C++
237 lines
10 KiB
C++
/* 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/optical_graph/OpticalGraph.h"
|
|
|
|
#include "model/OpticalModel.h"
|
|
#include "model/optical_graph/OpticalNode.h"
|
|
#include "model/optical_graph/OpticalLaser.h"
|
|
#include "model/optical_graph/OpticalModulator.h"
|
|
#include "model/optical_graph/OpticalFilter.h"
|
|
#include "model/optical_graph/OpticalDetector.h"
|
|
#include "model/optical_graph/OpticalWavelength.h"
|
|
|
|
namespace DSENT
|
|
{
|
|
// Initialize the next visited number to be one above the initial number
|
|
// used by OpticalNode
|
|
int OpticalGraph::msTreeNum = OpticalNode::OPTICAL_NODE_INIT_VISITED_NUM + 1;
|
|
|
|
OpticalGraph::OpticalGraph(const String& instance_name_, OpticalModel* model_)
|
|
: m_instance_name_(instance_name_), m_model_(model_)
|
|
{
|
|
|
|
}
|
|
|
|
OpticalGraph::~OpticalGraph()
|
|
{
|
|
|
|
}
|
|
|
|
const String& OpticalGraph::getInstanceName() const
|
|
{
|
|
return m_instance_name_;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Perform Datapath power optimization
|
|
//-------------------------------------------------------------------------
|
|
bool OpticalGraph::performPowerOpt(OpticalNode* node_, const WavelengthGroup& wavelengths_, unsigned int number_detectors_, double util_)
|
|
{
|
|
// Total number of iterations
|
|
unsigned int number_iterations = 1250;
|
|
// Maximum IL + ER
|
|
double IL_ER_max = 10;
|
|
// Figure out the step size used in the sweep
|
|
double step = (double) (IL_ER_max / sqrt(2 * number_iterations));
|
|
|
|
// Assume it is possible
|
|
bool possible = true;
|
|
|
|
// Begin optical data path power optimization
|
|
Log::printLine(getInstanceName() + " -> Beginning optical data path power optimization");
|
|
|
|
// Trace the specified wavelengths
|
|
OpticalWavelength* wavelength = traceWavelength(wavelengths_, node_);
|
|
|
|
// For each data path found in the wavelength
|
|
const vector<OpticalDataPath>* data_paths = wavelength->getDataPaths();
|
|
for (unsigned int i = 0; i < data_paths->size(); ++i)
|
|
{
|
|
const OpticalDataPath& data_path = data_paths->at(i);
|
|
// Default to worst possible modulator
|
|
double best_power = 1e99;
|
|
double best_IL = IL_ER_max - step;
|
|
double best_ER = step;
|
|
|
|
// Perform power optimization for this data path
|
|
Log::printLine(getInstanceName() + " -> Optimize data path - Laser = " + data_path.laser->getInstanceName()
|
|
+ ", Modulator = " + data_path.modulator->getInstanceName());
|
|
|
|
if (data_path.modulator->canOptimizeLoss())
|
|
{
|
|
// Iterate over IL and ER to find optimal set of IL and ER
|
|
for (double IL = step; IL < IL_ER_max; IL += step)
|
|
{
|
|
for (double ER = step; ER <= (IL_ER_max - IL); ER += step)
|
|
{
|
|
// Ask the modulator to try this new ER and IL
|
|
bool success = data_path.modulator->setModulatorSpec(IL, ER);
|
|
// If the modulator was successful
|
|
if (success)
|
|
{
|
|
double laser_power = wavelength->getLaserPower(number_detectors_);
|
|
double modulator_power = data_path.modulator->getPower(util_);
|
|
double total_power = laser_power + modulator_power;
|
|
// If this is the new lowest power point
|
|
if (total_power < best_power)
|
|
{
|
|
best_power = total_power;
|
|
best_IL = IL;
|
|
best_ER = ER;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set IL and ER to the best ones we found
|
|
bool success = data_path.modulator->setModulatorSpec(best_IL, best_ER);
|
|
// If the best one we found was still not possible...
|
|
possible = possible && success;
|
|
|
|
// Print best IL and ER
|
|
Log::printLine(getInstanceName() + " -> Best IL=" + (String) best_IL + ", Best ER=" + (String) best_ER +
|
|
", Best Laser/Mod Power=" + (String) best_power);
|
|
}
|
|
else
|
|
{
|
|
// Perform power optimization for this data path
|
|
Log::printLine(getInstanceName() + " -> Data path not set to allow optimization");
|
|
}
|
|
}
|
|
|
|
// End optical data path power optimization
|
|
Log::printLine(getInstanceName() + " -> End optical data path power optimization");
|
|
|
|
delete wavelength;
|
|
return possible;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Trace wavelength(s), returning a wavelength data structure
|
|
//-------------------------------------------------------------------------
|
|
OpticalWavelength* OpticalGraph::traceWavelength(const WavelengthGroup& wavelengths_, OpticalNode* node_)
|
|
{
|
|
setTreeNum(getTreeNum() + 1);
|
|
OpticalWavelength* wavelength = new OpticalWavelength("TraceWavelength", wavelengths_);
|
|
return traceWavelength(wavelength, node_, NULL, NULL, 0.0);
|
|
}
|
|
|
|
OpticalWavelength* OpticalGraph::traceWavelength(OpticalWavelength* wavelength_, OpticalNode* node_, OpticalLaser* laser_, OpticalModulator* modulator_, double loss_)
|
|
{
|
|
// If the node has already been visited, don't do anything!
|
|
if (node_->getVisitedNum() != getTreeNum())
|
|
{
|
|
// Set the new parity for this node
|
|
node_->setVisitedNum(getTreeNum());
|
|
|
|
// Calculate the loss of the current path
|
|
double current_loss = loss_ + node_->getLoss();
|
|
// Check if the current node is a laser, modulator or detector
|
|
if(node_->getType() == OpticalNode::LASER)
|
|
{
|
|
// Set the laser lighting up the wavelength
|
|
ASSERT(laser_ == NULL, "[Error] " + getInstanceName() + " -> Multiple " +
|
|
"Lasers lighting up the wavelength!");
|
|
laser_ = (OpticalLaser*) node_;
|
|
}
|
|
else if (node_->getType() == OpticalNode::MODULATOR)
|
|
{
|
|
// Check that the path already lit up by a laser and there are no
|
|
// modulators already driving data
|
|
ASSERT(laser_ != NULL, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
|
|
"modulator (" + node_->getInstanceName() + ") prior to being lit up by a laser!");
|
|
ASSERT(modulator_ == NULL, "[Error] " + getInstanceName() + " -> Two modulators are driving" +
|
|
" the same optical data path (" + node_->getInstanceName() + ")!");
|
|
modulator_ = (OpticalModulator*) node_;
|
|
}
|
|
else if (node_->getType() == OpticalNode::DETECTOR)
|
|
{
|
|
// Check that the path is both lit up by a laser and there is
|
|
// a modulator driving data
|
|
ASSERT(laser_ != NULL, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
|
|
"detector (" + node_->getInstanceName() + ") prior to being lit up by a laser!");
|
|
ASSERT(modulator_ != NULL, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
|
|
"detector (" + node_->getInstanceName() + ") prior to being driven by a modulator!");
|
|
// Add a detector to the wavelength
|
|
wavelength_->addDataPath(laser_, modulator_, (OpticalDetector*) node_, current_loss);
|
|
}
|
|
|
|
// Traverse downstream nodes to calculate the delay through each downstream path
|
|
vector<OpticalNode*>* d_nodes = node_->getDownstreamNodes();
|
|
bool trace_downstream = (node_->getType() != OpticalNode::DETECTOR);
|
|
// Do special things when traversing filters
|
|
if (node_->getType() == OpticalNode::FILTER)
|
|
{
|
|
OpticalFilter* filter_node = (OpticalFilter*) node_;
|
|
if (filter_node->isDropped(wavelength_->getWavelengths()))
|
|
traceWavelength(wavelength_, filter_node->getDropPort(), laser_, modulator_, loss_ + filter_node->getDropLoss());
|
|
|
|
// If the filter is not modeled as a complete drop, continue tracing downstream
|
|
trace_downstream = !filter_node->getDropAll();
|
|
}
|
|
|
|
if (trace_downstream)
|
|
{
|
|
// Trace downstream nodes
|
|
for (unsigned int i = 0; i < d_nodes->size(); ++i)
|
|
traceWavelength(wavelength_, d_nodes->at(i), laser_, modulator_, current_loss);
|
|
}
|
|
}
|
|
return wavelength_;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
OpticalGraph::OpticalGraph(const OpticalGraph& /* graph_ */)
|
|
{
|
|
// Disabled
|
|
}
|
|
|
|
OpticalModel* OpticalGraph::getModel()
|
|
{
|
|
return m_model_;
|
|
}
|
|
|
|
void OpticalGraph::setTreeNum(int tree_num_)
|
|
{
|
|
msTreeNum = tree_num_;
|
|
return;
|
|
}
|
|
|
|
int OpticalGraph::getTreeNum()
|
|
{
|
|
return msTreeNum;
|
|
}
|
|
|
|
} // namespace DSENT
|
|
|