1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
|