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