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