1 /* Copyright (c) 2012 Massachusetts Institute of Technology
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 #include "model/optical_graph/OpticalGraph.h"
25 #include "model/OpticalModel.h"
26 #include "model/optical_graph/OpticalNode.h"
27 #include "model/optical_graph/OpticalLaser.h"
28 #include "model/optical_graph/OpticalModulator.h"
29 #include "model/optical_graph/OpticalFilter.h"
30 #include "model/optical_graph/OpticalDetector.h"
31 #include "model/optical_graph/OpticalWavelength.h"
35 // Initialize the next visited number to be one above the initial number
36 // used by OpticalNode
37 int OpticalGraph::msTreeNum
= OpticalNode::OPTICAL_NODE_INIT_VISITED_NUM
+ 1;
39 OpticalGraph::OpticalGraph(const String
& instance_name_
, OpticalModel
* model_
)
40 : m_instance_name_(instance_name_
), m_model_(model_
)
45 OpticalGraph::~OpticalGraph()
50 const String
& OpticalGraph::getInstanceName() const
52 return m_instance_name_
;
55 //-------------------------------------------------------------------------
56 // Perform Datapath power optimization
57 //-------------------------------------------------------------------------
58 bool OpticalGraph::performPowerOpt(OpticalNode
* node_
, const WavelengthGroup
& wavelengths_
, unsigned int number_detectors_
, double util_
)
60 // Total number of iterations
61 unsigned int number_iterations
= 1250;
63 double IL_ER_max
= 10;
64 // Figure out the step size used in the sweep
65 double step
= (double) (IL_ER_max
/ sqrt(2 * number_iterations
));
67 // Assume it is possible
70 // Begin optical data path power optimization
71 Log::printLine(getInstanceName() + " -> Beginning optical data path power optimization");
73 // Trace the specified wavelengths
74 OpticalWavelength
* wavelength
= traceWavelength(wavelengths_
, node_
);
76 // For each data path found in the wavelength
77 const vector
<OpticalDataPath
>* data_paths
= wavelength
->getDataPaths();
78 for (unsigned int i
= 0; i
< data_paths
->size(); ++i
)
80 const OpticalDataPath
& data_path
= data_paths
->at(i
);
81 // Default to worst possible modulator
82 double best_power
= 1e99
;
83 double best_IL
= IL_ER_max
- step
;
84 double best_ER
= step
;
86 // Perform power optimization for this data path
87 Log::printLine(getInstanceName() + " -> Optimize data path - Laser = " + data_path
.laser
->getInstanceName()
88 + ", Modulator = " + data_path
.modulator
->getInstanceName());
90 if (data_path
.modulator
->canOptimizeLoss())
92 // Iterate over IL and ER to find optimal set of IL and ER
93 for (double IL
= step
; IL
< IL_ER_max
; IL
+= step
)
95 for (double ER
= step
; ER
<= (IL_ER_max
- IL
); ER
+= step
)
97 // Ask the modulator to try this new ER and IL
98 bool success
= data_path
.modulator
->setModulatorSpec(IL
, ER
);
99 // If the modulator was successful
102 double laser_power
= wavelength
->getLaserPower(number_detectors_
);
103 double modulator_power
= data_path
.modulator
->getPower(util_
);
104 double total_power
= laser_power
+ modulator_power
;
105 // If this is the new lowest power point
106 if (total_power
< best_power
)
108 best_power
= total_power
;
116 // Set IL and ER to the best ones we found
117 bool success
= data_path
.modulator
->setModulatorSpec(best_IL
, best_ER
);
118 // If the best one we found was still not possible...
119 possible
= possible
&& success
;
121 // Print best IL and ER
122 Log::printLine(getInstanceName() + " -> Best IL=" + (String
) best_IL
+ ", Best ER=" + (String
) best_ER
+
123 ", Best Laser/Mod Power=" + (String
) best_power
);
127 // Perform power optimization for this data path
128 Log::printLine(getInstanceName() + " -> Data path not set to allow optimization");
132 // End optical data path power optimization
133 Log::printLine(getInstanceName() + " -> End optical data path power optimization");
140 //-------------------------------------------------------------------------
141 // Trace wavelength(s), returning a wavelength data structure
142 //-------------------------------------------------------------------------
143 OpticalWavelength
* OpticalGraph::traceWavelength(const WavelengthGroup
& wavelengths_
, OpticalNode
* node_
)
145 setTreeNum(getTreeNum() + 1);
146 OpticalWavelength
* wavelength
= new OpticalWavelength("TraceWavelength", wavelengths_
);
147 return traceWavelength(wavelength
, node_
, NULL
, NULL
, 0.0);
150 OpticalWavelength
* OpticalGraph::traceWavelength(OpticalWavelength
* wavelength_
, OpticalNode
* node_
, OpticalLaser
* laser_
, OpticalModulator
* modulator_
, double loss_
)
152 // If the node has already been visited, don't do anything!
153 if (node_
->getVisitedNum() != getTreeNum())
155 // Set the new parity for this node
156 node_
->setVisitedNum(getTreeNum());
158 // Calculate the loss of the current path
159 double current_loss
= loss_
+ node_
->getLoss();
160 // Check if the current node is a laser, modulator or detector
161 if(node_
->getType() == OpticalNode::LASER
)
163 // Set the laser lighting up the wavelength
164 ASSERT(laser_
== NULL
, "[Error] " + getInstanceName() + " -> Multiple " +
165 "Lasers lighting up the wavelength!");
166 laser_
= (OpticalLaser
*) node_
;
168 else if (node_
->getType() == OpticalNode::MODULATOR
)
170 // Check that the path already lit up by a laser and there are no
171 // modulators already driving data
172 ASSERT(laser_
!= NULL
, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
173 "modulator (" + node_
->getInstanceName() + ") prior to being lit up by a laser!");
174 ASSERT(modulator_
== NULL
, "[Error] " + getInstanceName() + " -> Two modulators are driving" +
175 " the same optical data path (" + node_
->getInstanceName() + ")!");
176 modulator_
= (OpticalModulator
*) node_
;
178 else if (node_
->getType() == OpticalNode::DETECTOR
)
180 // Check that the path is both lit up by a laser and there is
181 // a modulator driving data
182 ASSERT(laser_
!= NULL
, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
183 "detector (" + node_
->getInstanceName() + ") prior to being lit up by a laser!");
184 ASSERT(modulator_
!= NULL
, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
185 "detector (" + node_
->getInstanceName() + ") prior to being driven by a modulator!");
186 // Add a detector to the wavelength
187 wavelength_
->addDataPath(laser_
, modulator_
, (OpticalDetector
*) node_
, current_loss
);
190 // Traverse downstream nodes to calculate the delay through each downstream path
191 vector
<OpticalNode
*>* d_nodes
= node_
->getDownstreamNodes();
192 bool trace_downstream
= (node_
->getType() != OpticalNode::DETECTOR
);
193 // Do special things when traversing filters
194 if (node_
->getType() == OpticalNode::FILTER
)
196 OpticalFilter
* filter_node
= (OpticalFilter
*) node_
;
197 if (filter_node
->isDropped(wavelength_
->getWavelengths()))
198 traceWavelength(wavelength_
, filter_node
->getDropPort(), laser_
, modulator_
, loss_
+ filter_node
->getDropLoss());
200 // If the filter is not modeled as a complete drop, continue tracing downstream
201 trace_downstream
= !filter_node
->getDropAll();
204 if (trace_downstream
)
206 // Trace downstream nodes
207 for (unsigned int i
= 0; i
< d_nodes
->size(); ++i
)
208 traceWavelength(wavelength_
, d_nodes
->at(i
), laser_
, modulator_
, current_loss
);
214 //-------------------------------------------------------------------------
215 OpticalGraph::OpticalGraph(const OpticalGraph
& /* graph_ */)
220 OpticalModel
* OpticalGraph::getModel()
225 void OpticalGraph::setTreeNum(int tree_num_
)
227 msTreeNum
= tree_num_
;
231 int OpticalGraph::getTreeNum()