diff options
Diffstat (limited to 'ext/dsent/model/optical_graph/OpticalGraph.cc')
-rw-r--r-- | ext/dsent/model/optical_graph/OpticalGraph.cc | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/ext/dsent/model/optical_graph/OpticalGraph.cc b/ext/dsent/model/optical_graph/OpticalGraph.cc new file mode 100644 index 000000000..424f2bcb2 --- /dev/null +++ b/ext/dsent/model/optical_graph/OpticalGraph.cc @@ -0,0 +1,216 @@ + +#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 + |