summaryrefslogtreecommitdiff
path: root/ext/dsent/model/optical_graph/OpticalGraph.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dsent/model/optical_graph/OpticalGraph.cc')
-rw-r--r--ext/dsent/model/optical_graph/OpticalGraph.cc216
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
+