sim, kvm: make KvmVM a System parameter
[gem5.git] / ext / dsent / model / optical_graph / OpticalGraph.cc
1 /* Copyright (c) 2012 Massachusetts Institute of Technology
2 *
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:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
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
19 * THE SOFTWARE.
20 */
21
22
23 #include "model/optical_graph/OpticalGraph.h"
24
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"
32
33 namespace DSENT
34 {
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;
38
39 OpticalGraph::OpticalGraph(const String& instance_name_, OpticalModel* model_)
40 : m_instance_name_(instance_name_), m_model_(model_)
41 {
42
43 }
44
45 OpticalGraph::~OpticalGraph()
46 {
47
48 }
49
50 const String& OpticalGraph::getInstanceName() const
51 {
52 return m_instance_name_;
53 }
54
55 //-------------------------------------------------------------------------
56 // Perform Datapath power optimization
57 //-------------------------------------------------------------------------
58 bool OpticalGraph::performPowerOpt(OpticalNode* node_, const WavelengthGroup& wavelengths_, unsigned int number_detectors_, double util_)
59 {
60 // Total number of iterations
61 unsigned int number_iterations = 1250;
62 // Maximum IL + ER
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));
66
67 // Assume it is possible
68 bool possible = true;
69
70 // Begin optical data path power optimization
71 Log::printLine(getInstanceName() + " -> Beginning optical data path power optimization");
72
73 // Trace the specified wavelengths
74 OpticalWavelength* wavelength = traceWavelength(wavelengths_, node_);
75
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)
79 {
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;
85
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());
89
90 if (data_path.modulator->canOptimizeLoss())
91 {
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)
94 {
95 for (double ER = step; ER <= (IL_ER_max - IL); ER += step)
96 {
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
100 if (success)
101 {
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)
107 {
108 best_power = total_power;
109 best_IL = IL;
110 best_ER = ER;
111 }
112 }
113 }
114 }
115
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;
120
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);
124 }
125 else
126 {
127 // Perform power optimization for this data path
128 Log::printLine(getInstanceName() + " -> Data path not set to allow optimization");
129 }
130 }
131
132 // End optical data path power optimization
133 Log::printLine(getInstanceName() + " -> End optical data path power optimization");
134
135 delete wavelength;
136 return possible;
137 }
138
139
140 //-------------------------------------------------------------------------
141 // Trace wavelength(s), returning a wavelength data structure
142 //-------------------------------------------------------------------------
143 OpticalWavelength* OpticalGraph::traceWavelength(const WavelengthGroup& wavelengths_, OpticalNode* node_)
144 {
145 setTreeNum(getTreeNum() + 1);
146 OpticalWavelength* wavelength = new OpticalWavelength("TraceWavelength", wavelengths_);
147 return traceWavelength(wavelength, node_, NULL, NULL, 0.0);
148 }
149
150 OpticalWavelength* OpticalGraph::traceWavelength(OpticalWavelength* wavelength_, OpticalNode* node_, OpticalLaser* laser_, OpticalModulator* modulator_, double loss_)
151 {
152 // If the node has already been visited, don't do anything!
153 if (node_->getVisitedNum() != getTreeNum())
154 {
155 // Set the new parity for this node
156 node_->setVisitedNum(getTreeNum());
157
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)
162 {
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_;
167 }
168 else if (node_->getType() == OpticalNode::MODULATOR)
169 {
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_;
177 }
178 else if (node_->getType() == OpticalNode::DETECTOR)
179 {
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);
188 }
189
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)
195 {
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());
199
200 // If the filter is not modeled as a complete drop, continue tracing downstream
201 trace_downstream = !filter_node->getDropAll();
202 }
203
204 if (trace_downstream)
205 {
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);
209 }
210 }
211 return wavelength_;
212 }
213
214 //-------------------------------------------------------------------------
215 OpticalGraph::OpticalGraph(const OpticalGraph& /* graph_ */)
216 {
217 // Disabled
218 }
219
220 OpticalModel* OpticalGraph::getModel()
221 {
222 return m_model_;
223 }
224
225 void OpticalGraph::setTreeNum(int tree_num_)
226 {
227 msTreeNum = tree_num_;
228 return;
229 }
230
231 int OpticalGraph::getTreeNum()
232 {
233 return msTreeNum;
234 }
235
236 } // namespace DSENT
237