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#include "model/optical/SWMRLink.h"
23
24#include "model/PortInfo.h"
25#include "model/TransitionInfo.h"
26#include "model/EventInfo.h"
27#include "model/optical_graph/OpticalGraph.h"
28#include "model/optical_graph/OpticalWaveguide.h"
29#include "model/optical/RingModulator.h"
30#include "model/optical/RingFilter.h"
31#include "model/optical/RingDetector.h"
32#include "model/optical/LaserSource.h"
33#include "model/optical/ThrottledLaserSource.h"
34
35namespace DSENT
36{
37 SWMRLink::SWMRLink(const String& instance_name_, const TechModel* tech_model_)
38 : OpticalModel(instance_name_, tech_model_)
39 {
40 initParameters();
41 initProperties();
42 }
43
44 SWMRLink::~SWMRLink()
45 {}
46
47 void SWMRLink::initParameters()
48 {
49 addParameterName("NumberReaders");
50 addParameterName("NumberWavelengths");
51 addParameterName("DataRate");
52 addParameterName("LaserType");
53 addParameterName("MaxReaders");
54 addParameterName("MinReaders");
55 addParameterName("OptimizeLoss", "TRUE");
56 return;
57 }
58
59 void SWMRLink::initProperties()
60 {
61 addPropertyName("Length");
62 addPropertyName("OptUtil", 0.5); // default to 50% utilization (a new word 50% of the time)
63 addPropertyName("ExtinctionRatio", 6); // default properties
64 addPropertyName("InsertionLoss", 2); // default properties
65 return;
66 }
67
68 void SWMRLink::constructModel()
69 {
70 // Get parameters
71 unsigned int number_wavelengths = getParameter("NumberWavelengths");
72 unsigned int number_readers = getParameter("NumberReaders");
73 unsigned int number_max_readers = std::min(number_readers, getParameter("MaxReaders").toUInt());
74 unsigned int number_min_readers = std::min(number_max_readers, getParameter("MinReaders").toUInt());
75
76 // Create electrical ports
77 createInputPort("CK");
78 createInputPort("In", makeNetIndex(0, number_wavelengths-1));
79 for (unsigned int i = 0; i < number_readers; ++i)
80 createOutputPort("Out" + (String) i, makeNetIndex(0, number_wavelengths-1));
81
82 // Create Waveguides
83 // Temporarily assume its all on one waveguide
84 createWaveguide("LaserToMod", makeWavelengthGroup(0, number_wavelengths-1));
85 for (unsigned int i = 0; i <= number_readers; ++i)
86 createWaveguide("WaveguideSegment[" + (String) i + "]", makeWavelengthGroup(0, number_wavelengths-1));
87
88 // Add area results
89 addAreaResult(new Result("Photonic"));
90 createElectricalResults();
91 // Setup idle event
92 getEventInfo("Idle")->setStaticTransitionInfos();
93 // Create a waveguide area result
94 addAreaResult(new AtomicResult("Waveguide"));
95 getAreaResult("Photonic")->addSubResult(getAreaResult("Waveguide"), "Waveguide", 1.0);
96 // Add results
97 addNddPowerResult(new Result("Laser"));
98 // Add event result
99 createElectricalEventResult("BroadcastFlit");
100
101 for (unsigned int i = number_min_readers; i <= number_max_readers; ++i)
102 createElectricalEventResult("MulticastFlit" + (String) i);
103
104 buildLaser();
105 buildModulator();
106 buildDetectors();
107
108 return;
109 }
110
111 void SWMRLink::updateModel()
112 {
113 // Get parameters
114 double data_rate = getParameter("DataRate");
115 unsigned int number_readers = getParameter("NumberReaders");
116
117 // Get properties
118 double length = getProperty("Length");
119 const String& extinction_ratio = getProperty("ExtinctionRatio");
120 const String& insertion_loss = getProperty("InsertionLoss");
121 const double opt_util = getProperty("OptUtil");
122
123 // Calculate loss for each waveguide segment
124 double segment_length = (double) length / number_readers;
125 double segment_loss = getTechModel()->get("Waveguide->LossPerMeter").toDouble() * segment_length;
126 // Set loss of each waveguide segment
127 for (unsigned int i = 0; i < number_readers; ++i)
128 getWaveguide("WaveguideSegment[" + (String) i + "]")->setLoss(segment_loss);
129 // Calculate waveguide area
130 double waveguide_area = length * getTechModel()->get("Waveguide->Pitch").toDouble();
131 getAreaResult("Waveguide")->setValue(waveguide_area);
132
133 // Update the laser
134 Model* laser = getSubInstance("Laser");
135 laser->setProperty("LaserEventTime", 1.0 / data_rate);
136 laser->setProperty("OptUtil", opt_util);
137 laser->update();
138
139 // Update the modulator
140 Model* modulator = getSubInstance("Modulator");
141 modulator->setProperty("ExtinctionRatio", extinction_ratio);
142 modulator->setProperty("InsertionLoss", insertion_loss);
143 modulator->update();
144
145 // Update all receivers
146 for (unsigned int i = 0; i < number_readers; ++i)
147 {
148 Model* detector = getSubInstance("Detector_" + (String) i);
149 detector->update();
150 }
151
152 return;
153 }
154
155 void SWMRLink::propagateTransitionInfo()
156 {
157 // Get parameters
158 const String& laser_type = getParameter("LaserType");
159 unsigned int number_readers = getParameter("NumberReaders");
160
161 // Set transition info for the modulator
162 OpticalModel* modulator = (OpticalModel*) getSubInstance("Modulator");
163 propagatePortTransitionInfo(modulator, "In", "In");
164 modulator->use();
165
166 // Modulator out transition info
167 const TransitionInfo& mod_out_transitions = modulator->getOpticalOutputPort("Out")->getTransitionInfo();
168
169 // Set transition info for all receivers
170 for (unsigned int i = 0; i < number_readers; ++i)
171 {
172 OpticalModel* detector = (OpticalModel*) getSubInstance("Detector_" + (String) i);
173 detector->getOpticalInputPort("In")->setTransitionInfo(mod_out_transitions);
174 detector->use();
175
176 // Propagate output transition info to output
177 propagatePortTransitionInfo("Out" + (String) i, detector, "Out");
178 }
179
180 // Set enable signals for the laser, if applicable
181 if (laser_type == "Throttled")
182 {
183 // Figure out how many cycles the laser needs to be on
184 double cycles = getInputPort("In")->getTransitionInfo().getFrequencyMultiplier();
185
186 OpticalModel* laser = (OpticalModel*) getSubInstance("Laser");
187 laser->getInputPort("LaserEnable")->setTransitionInfo(TransitionInfo(0.0, 1.0, cycles - 1.0));
188 laser->use();
189 }
190 return;
191 }
192
193 void SWMRLink::buildLaser()
194 {
195 // Get parameters
196 unsigned int number_wavelengths = getParameter("NumberWavelengths");
197 unsigned int number_readers = getParameter("NumberReaders");
198 unsigned int number_max_readers = std::min(number_readers, getParameter("MaxReaders").toUInt());
199 unsigned int number_min_readers = std::min(number_max_readers, getParameter("MinReaders").toUInt());
200 const String& laser_type = getParameter("LaserType");
201
202 // Create laser
203 OpticalModel* laser = NULL;
204 if (laser_type == "Throttled")
205 laser = new ThrottledLaserSource("Laser", getTechModel());
206 else if (laser_type == "Standard")
207 laser = new LaserSource("Laser", getTechModel());
208 else
209 ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown laser type '" + laser_type + "'!");
210
211 laser->setParameter("OutStart", 0);
212 laser->setParameter("OutEnd", number_wavelengths-1);
213 laser->setParameter("MaxDetectors", number_max_readers);
214 laser->setParameter("MinDetectors", number_min_readers);
215 laser->construct();
216
217 addSubInstances(laser, 1.0);
218 getAreaResult("Photonic")->addSubResult(laser->getAreaResult("Photonic"), "Laser", 1.0);
219 // Connect laser output port
220 opticalPortConnect(laser, "Out", "LaserToMod");
221
222 // Without laser gating, laser is pure NDD power
223 if (laser_type == "Standard")
224 getNddPowerResult("Laser")->addSubResult(laser->getNddPowerResult("Laser"), "Laser", 1.0);
225 // With laser power gating, laser is an event
226 else
227 {
228 // If laser is throttled, only pay for the amount needed to reach some number of readers
229 getEventResult("BroadcastFlit")->addSubResult(laser->getEventResult("Laser" + (String) number_max_readers), "Laser", 1.0);
230 for (unsigned int i = number_min_readers; i <= number_max_readers; ++i)
231 getEventResult("MulticastFlit" + (String) i)->addSubResult(laser->getEventResult("Laser" + (String) i), "Laser", 1.0);
232 }
233
234 return;
235 }
236
237 void SWMRLink::buildModulator()
238 {
239 // Get parameters
240 double data_rate = getParameter("DataRate");
241 const String& optimize_loss = getParameter("OptimizeLoss");
242 unsigned int number_wavelengths = getParameter("NumberWavelengths");
243 unsigned int number_readers = getParameter("NumberReaders");
244 unsigned int number_max_readers = std::min(number_readers, getParameter("MaxReaders").toUInt());
245 unsigned int number_min_readers = std::min(number_max_readers, getParameter("MinReaders").toUInt());
246
247 // Create modulator
248 RingModulator* modulator = new RingModulator("Modulator", getTechModel());
249 modulator->setParameter("DataRate", data_rate);
250 modulator->setParameter("InStart", 0);
251 modulator->setParameter("InEnd", number_wavelengths-1);
252 modulator->setParameter("ModStart", 0);
253 modulator->setParameter("ModEnd", number_wavelengths-1);
254 modulator->setParameter("OptimizeLoss", optimize_loss);
255 modulator->construct();
256 addSubInstances(modulator, 1.0);
257 getAreaResult("Photonic")->addSubResult(modulator->getAreaResult("Photonic"), "Modulator", 1.0);
258 addElectricalSubResults(modulator, 1.0);
259
260 // Connect electrical port
261 portConnect(modulator, "In", "In");
262 // Connect modulator input, output port
263 opticalPortConnect(modulator, "In", "LaserToMod");
264 opticalPortConnect(modulator, "Out", "WaveguideSegment[0]");
265
266 // Add modulator energy event for all broadcast events
267 getEventResult("BroadcastFlit")->addSubResult(modulator->getEventResult("Modulate"), "Modulator", 1.0);
268 for (unsigned int i = number_min_readers; i <= number_max_readers; ++i)
269 getEventResult("MulticastFlit" + (String) i)->addSubResult(modulator->getEventResult("Modulate"), "Modulator", 1.0);
270
271 return;
272 }
273
274 void SWMRLink::buildDetectors()
275 {
276 // Get parameters
277 double data_rate = getParameter("DataRate");
278 unsigned int number_wavelengths = getParameter("NumberWavelengths");
279 unsigned int number_readers = getParameter("NumberReaders");
280 unsigned int number_max_readers = std::min(number_readers, getParameter("MaxReaders").toUInt());
281 unsigned int number_min_readers = std::min(number_max_readers, getParameter("MinReaders").toUInt());
282
283 // Create a SWMR Configuration
284 for (unsigned int i = 0; i < number_readers; ++i)
285 {
286 String n = (String) i;
287
288 // Create resonant ring detector
289 RingDetector* detector = new RingDetector("Detector_" + n, getTechModel());
290 detector->setParameter("DataRate", data_rate);
291 detector->setParameter("InStart", 0);
292 detector->setParameter("InEnd", number_wavelengths-1);
293 detector->setParameter("DetStart", 0);
294 detector->setParameter("DetEnd", number_wavelengths-1);
295 detector->setParameter("DropAll", "FALSE");
296 detector->setParameter("Topology", RingDetector::INTEGRATINGSENSEAMP);
297 detector->construct();
298 addSubInstances(detector, 1.0);
299 getAreaResult("Photonic")->addSubResult(detector->getAreaResult("Photonic"), "Detector_" + n, 1.0);
300 addElectricalSubResults(detector, 1.0);
301
302 // connect to electrical port
303 portConnect(detector, "Out", "Out" + (String) i);
304 // connect optical input, output port
305 opticalPortConnect(detector, "In", "WaveguideSegment[" + (String) i + "]");
306 opticalPortConnect(detector, "Out", "WaveguideSegment[" + (String) (i + 1) + "]");
307 }
308
309 // Add an average receiver energy for all multicast events (and broadcast)
310 Result* broadcast_event = getEventResult("BroadcastFlit");
311 for (unsigned int i = 0; i < number_readers; ++i)
312 {
313 const String detector_name = "Detector_" + (String) i;
314 broadcast_event->addSubResult(getSubInstance(detector_name)->getEventResult("Receive"), detector_name, 1.0);
315 }
316 for (unsigned int i = number_min_readers; i <= number_max_readers; ++i)
317 {
318 Result* multicast_event = getEventResult("MulticastFlit" + (String) i);
319 for (unsigned int j = 0; j < number_readers; ++j)
320 {
321 const String detector_name = "Detector_" + (String) j;
322 multicast_event->addSubResult(getSubInstance(detector_name)->getEventResult("Receive"), detector_name, (double) i / number_readers);
323 }
324 }
325
326 return;
327 }
328
329} // namespace DSENT
330