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/OpticalModel.h"
23
24#include "model/PortInfo.h"
25#include "model/EventInfo.h"
26#include "model/optical_graph/OpticalWaveguide.h"
27#include "model/optical_graph/OpticalNode.h"
28#include "model/optical_graph/OpticalLaser.h"
29#include "model/optical_graph/OpticalModulator.h"
30#include "model/optical_graph/OpticalFilter.h"
31#include "model/optical_graph/OpticalDetector.h"
32#include "model/optical_graph/OpticalWavelength.h"
33
34namespace DSENT
35{
36    OpticalModel::OpticalModel(const String& instance_name_, const TechModel* tech_model_)
37        : ElectricalModel(instance_name_, tech_model_)
38    {
39        m_optical_input_ports_ = new Map<PortInfo*>;
40        m_optical_output_ports_ = new Map<PortInfo*>;
41
42        m_waveguides_ = new Map<OpticalWaveguide*>;
43        m_lasers_ = new Map<OpticalLaser*>;
44        m_modulators_ = new Map<OpticalModulator*>;
45        m_filters_ = new Map<OpticalFilter*>;
46        m_detectors_ = new Map<OpticalDetector*>;
47    }
48
49    OpticalModel::~OpticalModel()
50    {
51        delete m_optical_input_ports_;
52        delete m_optical_output_ports_;
53        deletePtrMap<OpticalWaveguide>(m_waveguides_);
54        deletePtrMap<OpticalLaser>(m_lasers_);
55        deletePtrMap<OpticalModulator>(m_modulators_);
56        deletePtrMap<OpticalFilter>(m_filters_);
57        deletePtrMap<OpticalDetector>(m_detectors_);
58        m_optical_input_ports_ = NULL;
59        m_optical_output_ports_ = NULL;
60        m_waveguides_ = NULL;
61        m_lasers_ = NULL;
62        m_modulators_ = NULL;
63        m_filters_ = NULL;
64        m_detectors_ = NULL;
65    }
66
67    // Connect an optical port (input or output) to some OpticalWaveguide
68    void OpticalModel::opticalPortConnect(OpticalModel* connect_model_, const String& port_name_, const String& waveguide_name_)
69    {
70        // Check that the connecting waveguide exists
71        ASSERT(m_waveguides_->keyExist(waveguide_name_), "[Error] " + getInstanceName() +
72            " -> Waveguide '" + waveguide_name_ + "' does not exist!");
73
74        // Check whether the port name is an input or output, assertion error if neither
75        bool is_input = connect_model_->getOpticalInputs()->keyExist(port_name_);
76        bool is_output = connect_model_->getOpticalOutputs()->keyExist(port_name_);
77        ASSERT(is_input || is_output, "[Error] " + getInstanceName() + " -> Model '" + connect_model_->getInstanceName() +
78            "' does not have a port named '" + port_name_ + "'!");
79
80        // Get the two waveguides
81        OpticalWaveguide* port_waveguide = connect_model_->getWaveguide(port_name_);
82        OpticalWaveguide* connect_waveguide = getWaveguide(waveguide_name_);
83
84        // Check that the two waveguides expect the same wavelengths
85        ASSERT((port_waveguide->getWavelengths().first == connect_waveguide->getWavelengths().first) &&
86            (port_waveguide->getWavelengths().second == connect_waveguide->getWavelengths().second),
87            "[Error] " + getInstanceName() + " -> Optical port expects different wavelengths for Model '" +
88            connect_model_->getInstanceName() + "." + port_name_ + "' and waveguide '" + waveguide_name_ + "'!");
89
90        if(is_input)
91        {
92            connect_waveguide->addDownstreamNode(port_waveguide);
93        }
94        else if(is_output)
95        {
96            port_waveguide->addDownstreamNode(connect_waveguide);
97        }
98    }
99
100    //Get Waveguides
101    const Map<OpticalWaveguide*>* OpticalModel::getWaveguides() const
102    {
103        return m_waveguides_;
104    }
105
106    OpticalWaveguide* OpticalModel::getWaveguide(const String& name_)
107    {
108        return m_waveguides_->get(name_);
109    }
110
111    //Get Lasers
112    const Map<OpticalLaser*>* OpticalModel::getLasers() const
113    {
114        return m_lasers_;
115    }
116
117    OpticalLaser* OpticalModel::getLaser(const String& name_)
118    {
119        return m_lasers_->get(name_);
120    }
121
122    //Get Modulators
123    const Map<OpticalModulator*>* OpticalModel::getModulators() const
124    {
125        return m_modulators_;
126    }
127
128    OpticalModulator* OpticalModel::getModulator(const String& name_)
129    {
130        return m_modulators_->get(name_);
131    }
132
133    //Get Filters
134    const Map<OpticalFilter*>* OpticalModel::getFilters() const
135    {
136        return m_filters_;
137    }
138
139    OpticalFilter* OpticalModel::getFilter(const String& name_)
140    {
141        return m_filters_->get(name_);
142    }
143
144    //Get Detectors
145    const Map<OpticalDetector*>* OpticalModel::getDetectors() const
146    {
147        return m_detectors_;
148    }
149
150    OpticalDetector* OpticalModel::getDetector(const String& name_)
151    {
152        return m_detectors_->get(name_);
153    }
154
155    //Get Inputs
156    const Map<PortInfo*>* OpticalModel::getOpticalInputs() const
157    {
158        return m_optical_input_ports_;
159    }
160
161    PortInfo* OpticalModel::getOpticalInputPort(const String& name_)
162    {
163        ASSERT(m_optical_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
164                " -> Input port (" + name_ + ") does not exist");
165
166        return m_optical_input_ports_->get(name_);
167    }
168
169    const PortInfo* OpticalModel::getOpticalInputPort(const String& name_) const
170    {
171        ASSERT(m_optical_input_ports_->keyExist(name_), "[Error] " + getInstanceName() +
172                " -> Input port (" + name_ + ") does not exist");
173
174        return m_optical_input_ports_->get(name_);
175    }
176
177    //Get Outputs
178    const Map<PortInfo*>* OpticalModel::getOpticalOutputs() const
179    {
180        return m_optical_output_ports_;
181    }
182
183    PortInfo* OpticalModel::getOpticalOutputPort(const String& name_)
184    {
185        ASSERT(m_optical_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
186                " -> Input port (" + name_ + ") does not exist");
187
188        return m_optical_output_ports_->get(name_);
189    }
190
191    const PortInfo* OpticalModel::getOpticalOutputPort(const String& name_) const
192    {
193        ASSERT(m_optical_output_ports_->keyExist(name_), "[Error] " + getInstanceName() +
194                " -> Input port (" + name_ + ") does not exist");
195
196        return m_optical_output_ports_->get(name_);
197    }
198
199    //-------------------------------------------------------------------------
200    //  Optical Connectivity Creation Functions
201    //-------------------------------------------------------------------------
202    void OpticalModel::createOpticalInputPort(const String& name_, const WavelengthGroup& wavelength_group_)
203    {
204        // Create the new waveguides
205        // This should already check that it has not been previously declared
206        createWaveguide(name_, wavelength_group_);
207        // Add the waveguide name to list of input ports
208        m_optical_input_ports_->set(name_, new PortInfo(name_, wavelength_group_));
209        return;
210    }
211
212    void OpticalModel::createOpticalOutputPort(const String& name_, const WavelengthGroup& wavelength_group_)
213    {
214        // Create the new waveguides (including its waveguide reference)
215        // This should already check that it has not been previously declared
216        createWaveguide(name_, wavelength_group_);
217        // Add the waveguide name to list of output ports
218        m_optical_output_ports_->set(name_, new PortInfo(name_, wavelength_group_));
219        return;
220    }
221
222    // Waveguide creation
223    void OpticalModel::createWaveguide(const String& name_, const WavelengthGroup& wavelengths_)
224    {
225        // Check that the waveguide hasn't been previously declared
226        ASSERT( !m_waveguides_->keyExist(name_), "[Error] " + getInstanceName() +
227            " -> Redeclaration of waveguide " + name_);
228        m_waveguides_->set(name_, new OpticalWaveguide(name_, this, wavelengths_));
229        return;
230    }
231
232    // Laser creation
233    void OpticalModel::createLaser(const String& name_, const WavelengthGroup& wavelengths_)
234    {
235        // Check that the laser hasn't been previously declared
236        ASSERT( !m_lasers_->keyExist(name_), "[Error] " + getInstanceName() +
237            " -> Redeclaration of laser " + name_);
238        m_lasers_->set(name_, new OpticalLaser(name_, this, wavelengths_));
239        return;
240    }
241
242    // Modulator creation
243    void OpticalModel::createModulator(const String& name_, const WavelengthGroup& wavelengths_, bool opt_loss_, OpticalTransmitter* transmitter_)
244    {
245        // Check that the modulator hasn't been previously declared
246        ASSERT( !m_modulators_->keyExist(name_), "[Error] " + getInstanceName() +
247            " -> Redeclaration of modulator " + name_);
248        m_modulators_->set(name_, new OpticalModulator(name_, this, wavelengths_, opt_loss_, transmitter_));
249        return;
250    }
251
252    // Modulator Multiplier creation
253    void OpticalModel::createFilter(const String& name_, const WavelengthGroup& wavelengths_, bool drop_all_, const WavelengthGroup& drop_wavelengths_)
254    {
255        // Check that the filter hasn't been previously declared
256        ASSERT( !m_filters_->keyExist(name_), "[Error] " + getInstanceName() +
257            " -> Redeclaration of filter " + name_);
258        m_filters_->set(name_, new OpticalFilter(name_, this, wavelengths_, drop_all_, drop_wavelengths_));
259        return;
260    }
261
262    // Detector creation
263    void OpticalModel::createDetector(const String& name_, const WavelengthGroup& wavelengths_, OpticalReceiver* receiver_)
264    {
265        // Check that the detector hasn't been previously declared
266        ASSERT( !m_detectors_->keyExist(name_), "[Error] " + getInstanceName() +
267            " -> Redeclaration of detector " + name_);
268        m_detectors_->set(name_, new OpticalDetector(name_, this, wavelengths_, receiver_));
269        return;
270    }
271
272    //-------------------------------------------------------------------------
273
274    // Assign a waveguide to be downstream from another waveguide
275    // assign downtream_waveguide_name_ = upstream_waveguide_name_
276    void OpticalModel::opticalAssign(const String& downstream_waveguide_name_, const String& upstream_waveguide_name_)
277    {
278        ASSERT(getWaveguides()->keyExist(downstream_waveguide_name_), "[Error] " + getInstanceName() + " -> Waveguide '" +
279            downstream_waveguide_name_ + "' does not exist!");
280
281        ASSERT(getWaveguides()->keyExist(upstream_waveguide_name_), "[Error] " + getInstanceName() + " -> Waveguide '" +
282            upstream_waveguide_name_ + "' does not exist!");
283
284        // Get the two waveguides
285        OpticalWaveguide* upstream_waveguide = getWaveguide(upstream_waveguide_name_);
286        OpticalWaveguide* downstream_waveguide = getWaveguide(downstream_waveguide_name_);
287
288        // Check that the two waveguides expect the same wavelengths
289        ASSERT((upstream_waveguide->getWavelengths().first == downstream_waveguide->getWavelengths().first) &&
290            (upstream_waveguide->getWavelengths().second == downstream_waveguide->getWavelengths().second),
291            "[Error] " + getInstanceName() + " -> Assignment expects different wavelengths for waveguide '" +
292                upstream_waveguide_name_ + "' and waveguide '" + downstream_waveguide_name_ + "'!");
293
294        // Connect the downstream waveguide and the upstream waveguide
295        upstream_waveguide->addDownstreamNode(downstream_waveguide);
296        return;
297    }
298} // namespace DSENT
299