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/network/PhotonicClos.h"
23
24#include <cmath>
25
26#include "model/ModelGen.h"
27#include "model/timing_graph/ElectricalTimingTree.h"
28#include "model/timing_graph/ElectricalNet.h"
29
30namespace DSENT
31{
32    using std::sqrt;
33
34    PhotonicClos::PhotonicClos(const String& instance_name_, const TechModel* tech_model_)
35        : ElectricalModel(instance_name_, tech_model_)
36    {
37        initParameters();
38        initProperties();
39    }
40
41    PhotonicClos::~PhotonicClos()
42    {}
43
44    void PhotonicClos::initParameters()
45    {
46        // Clock Frequency
47        addParameterName("Frequency");
48        // Physical Parameters
49        addParameterName("NumberInputSites");
50        addParameterName("NumberOutputSites");
51        addParameterName("NumberBitsPerFlit");
52        // Number of each type of routers
53        addParameterName("NumberIngressRouters");
54        addParameterName("NumberMiddleRouters");
55        addParameterName("NumberEgressRouters");
56        // Optical link parameters
57        addParameterName("SWSR->LinkDataRate");
58        addParameterName("SWSR->LaserType");
59        addParameterName("SWSR->RingTuningMethod");
60        // Router parameters
61        addParameterName("Router->NumberVirtualNetworks");
62        addParameterName("Router->NumberVirtualChannelsPerVirtualNetwork");
63        addParameterName("Router->NumberBuffersPerVirtualChannel");
64        addParameterName("Router->InputPort->BufferModel");
65        addParameterName("Router->CrossbarModel");
66        addParameterName("Router->SwitchAllocator->ArbiterModel");
67        addParameterName("Router->ClockTreeModel");
68        addParameterName("Router->ClockTree->NumberLevels");
69        addParameterName("Router->ClockTree->WireLayer");
70        addParameterName("Router->ClockTree->WireWidthMultiplier");
71        addParameterName("Router->ClockTree->WireSpacingMultiplier", 3.0);
72        // Link parameters
73        addParameterName("Link->WireLayer");
74        addParameterName("Link->WireWidthMultiplier");
75        addParameterName("Link->WireSpacingMultiplier");
76        return;
77    }
78
79    void PhotonicClos::initProperties()
80    {
81        addPropertyName("InputSitePitch");
82        addPropertyName("OutputSitePitch");
83		addPropertyName("SWSR->OptUtil", 1.0);
84        return;
85    }
86
87    PhotonicClos* PhotonicClos::clone() const
88    {
89        // TODO
90        return NULL;
91    }
92
93    void PhotonicClos::constructModel()
94    {
95        // Get input parameters
96        double clock_freq = getParameter("Frequency");
97        unsigned int number_input_sites = getParameter("NumberInputSites").toUInt();
98        unsigned int number_output_sites = getParameter("NumberOutputSites").toUInt();
99        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
100        unsigned int number_ingress_routers = getParameter("NumberIngressRouters").toUInt();
101        unsigned int number_middle_routers = getParameter("NumberMiddleRouters").toUInt();
102        unsigned int number_egress_routers = getParameter("NumberEgressRouters").toUInt();
103
104        ASSERT(clock_freq > 0, "[Error] " + getInstanceName() +
105                " -> Clock frequency must be > 0!");
106        ASSERT(number_input_sites > 0, "[Error] " + getInstanceName() +
107                " -> Number of input sites must be > 0!");
108        ASSERT(number_output_sites > 0, "[Error] " + getInstanceName() +
109                " -> Number of output sites must be > 0!");
110        ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() +
111                " -> Number of bits per flit must be > 0!");
112        ASSERT(number_ingress_routers > 0, "[Error] " + getInstanceName() +
113                " -> Number of ingress routers must be > 0!");
114        ASSERT(number_middle_routers > 0, "[Error] " + getInstanceName() +
115                " -> Number of middle routers must be > 0!");
116        ASSERT(number_egress_routers > 0, "[Error] " + getInstanceName() +
117                " -> Number of egress routers must be > 0!");
118
119        // Get input parameters that will be forwarded to the sub instances
120        const String& swsr_link_data_rate = getParameter("SWSR->LinkDataRate");
121        const String& swsr_laser_type = getParameter("SWSR->LaserType");
122        const String& swsr_ring_tuning_method = getParameter("SWSR->RingTuningMethod");
123        const String& router_number_vns = getParameter("Router->NumberVirtualNetworks");
124        const String& router_number_vcs_per_vn = getParameter("Router->NumberVirtualChannelsPerVirtualNetwork");
125        const String& router_number_bufs_per_vc = getParameter("Router->NumberBuffersPerVirtualChannel");
126        const String& router_buffer_model = getParameter("Router->InputPort->BufferModel");
127        const String& router_crossbar_model = getParameter("Router->CrossbarModel");
128        const String& link_wire_layer = getParameter("Link->WireLayer");
129        const String& link_wire_width_multiplier = getParameter("Link->WireWidthMultiplier");
130        const String& link_wire_spacing_multiplier = getParameter("Link->WireSpacingMultiplier");
131
132        // Calculate properties from input parameters
133        unsigned int ingress_router_number_input_ports = number_input_sites / number_ingress_routers;
134        unsigned int ingress_router_number_output_ports = number_middle_routers;
135        unsigned int middle_router_number_input_ports = number_ingress_routers;
136        unsigned int middle_router_number_output_ports = number_egress_routers;
137        unsigned int egress_router_number_input_ports = number_middle_routers;
138        unsigned int egress_router_number_output_ports = number_output_sites / number_egress_routers;
139        unsigned int number_input_to_ingress_links = number_input_sites;
140        unsigned int number_ingress_to_middle_links = number_ingress_routers * number_middle_routers;
141        unsigned int number_middle_to_egress_links = number_middle_routers * number_egress_routers;
142        unsigned int number_egress_to_output_links = number_output_sites;
143
144        getGenProperties()->set("NumberInputSitesPerIngressRouter", ingress_router_number_input_ports);
145        getGenProperties()->set("NumberOutputSitesPerEgressRouter", egress_router_number_output_ports);
146        getGenProperties()->set("IngressRouter->NumberInputPorts", ingress_router_number_input_ports);
147        getGenProperties()->set("IngressRouter->NumberOutputPorts", ingress_router_number_output_ports);
148        getGenProperties()->set("MiddleRouter->NumberInputPorts", middle_router_number_input_ports);
149        getGenProperties()->set("MiddleRouter->NumberOutputPorts", middle_router_number_output_ports);
150        getGenProperties()->set("EgressRouter->NumberInputPorts", egress_router_number_input_ports);
151        getGenProperties()->set("EgressRouter->NumberOutputPorts", egress_router_number_output_ports);
152
153        // Create ports
154        createInputPort("CK");
155
156        // Init ingress router
157        ElectricalModel* ingress_router = (ElectricalModel*)ModelGen::createModel("Router", "IngressRouter", getTechModel());
158        ingress_router->setParameter("NumberInputPorts", ingress_router_number_input_ports);
159        ingress_router->setParameter("NumberOutputPorts", ingress_router_number_output_ports);
160        ingress_router->setParameter("NumberVirtualNetworks", router_number_vns);
161        ingress_router->setParameter("NumberVirtualChannelsPerVirtualNetwork", router_number_vcs_per_vn);
162        ingress_router->setParameter("NumberBuffersPerVirtualChannel", router_number_bufs_per_vc);
163        ingress_router->setParameter("NumberBitsPerFlit", number_bits_per_flit);
164        ingress_router->setParameter("InputPort->BufferModel", router_buffer_model);
165        ingress_router->setParameter("CrossbarModel", router_crossbar_model);
166        ingress_router->setParameter("SwitchAllocator->ArbiterModel", getParameter("Router->SwitchAllocator->ArbiterModel"));
167        ingress_router->setParameter("ClockTreeModel", getParameter("Router->ClockTreeModel"));
168        ingress_router->setParameter("ClockTree->NumberLevels", getParameter("Router->ClockTree->NumberLevels"));
169        ingress_router->setParameter("ClockTree->WireLayer", getParameter("Router->ClockTree->WireLayer"));
170        ingress_router->setParameter("ClockTree->WireWidthMultiplier", getParameter("Router->ClockTree->WireWidthMultiplier"));
171        ingress_router->setParameter("ClockTree->WireSpacingMultiplier", getParameter("Router->ClockTree->WireSpacingMultiplier"));
172        ingress_router->construct();
173        // Init middle routers
174        ElectricalModel* middle_router = (ElectricalModel*)ModelGen::createModel("Router", "MiddleRouter", getTechModel());
175        middle_router->setParameter("NumberInputPorts", middle_router_number_input_ports);
176        middle_router->setParameter("NumberOutputPorts", middle_router_number_output_ports);
177        middle_router->setParameter("NumberVirtualNetworks", router_number_vns);
178        middle_router->setParameter("NumberVirtualChannelsPerVirtualNetwork", router_number_vcs_per_vn);
179        middle_router->setParameter("NumberBuffersPerVirtualChannel", router_number_bufs_per_vc);
180        middle_router->setParameter("NumberBitsPerFlit", number_bits_per_flit);
181        middle_router->setParameter("InputPort->BufferModel", router_buffer_model);
182        middle_router->setParameter("CrossbarModel", router_crossbar_model);
183        middle_router->setParameter("SwitchAllocator->ArbiterModel", getParameter("Router->SwitchAllocator->ArbiterModel"));
184        middle_router->setParameter("ClockTreeModel", getParameter("Router->ClockTreeModel"));
185        middle_router->setParameter("ClockTree->NumberLevels", getParameter("Router->ClockTree->NumberLevels"));
186        middle_router->setParameter("ClockTree->WireLayer", getParameter("Router->ClockTree->WireLayer"));
187        middle_router->setParameter("ClockTree->WireWidthMultiplier", getParameter("Router->ClockTree->WireWidthMultiplier"));
188        middle_router->setParameter("ClockTree->WireSpacingMultiplier", getParameter("Router->ClockTree->WireSpacingMultiplier"));
189        middle_router->construct();
190        // Init egress routers
191        ElectricalModel* egress_router = (ElectricalModel*)ModelGen::createModel("Router", "EgressRouter", getTechModel());
192        egress_router->setParameter("NumberInputPorts", egress_router_number_input_ports);
193        egress_router->setParameter("NumberOutputPorts", egress_router_number_output_ports);
194        egress_router->setParameter("NumberVirtualNetworks", router_number_vns);
195        egress_router->setParameter("NumberVirtualChannelsPerVirtualNetwork", router_number_vcs_per_vn);
196        egress_router->setParameter("NumberBuffersPerVirtualChannel", router_number_bufs_per_vc);
197        egress_router->setParameter("NumberBitsPerFlit", number_bits_per_flit);
198        egress_router->setParameter("InputPort->BufferModel", router_buffer_model);
199        egress_router->setParameter("CrossbarModel", router_crossbar_model);
200        egress_router->setParameter("SwitchAllocator->ArbiterModel", getParameter("Router->SwitchAllocator->ArbiterModel"));
201        egress_router->setParameter("ClockTreeModel", getParameter("Router->ClockTreeModel"));
202        egress_router->setParameter("ClockTree->NumberLevels", getParameter("Router->ClockTree->NumberLevels"));
203        egress_router->setParameter("ClockTree->WireLayer", getParameter("Router->ClockTree->WireLayer"));
204        egress_router->setParameter("ClockTree->WireWidthMultiplier", getParameter("Router->ClockTree->WireWidthMultiplier"));
205        egress_router->setParameter("ClockTree->WireSpacingMultiplier", getParameter("Router->ClockTree->WireSpacingMultiplier"));
206        egress_router->construct();
207        // Init input to ingress link
208        ElectricalModel* input_to_ingress_link = (ElectricalModel*)ModelGen::createModel("RepeatedLink", "InputToIngressLink", getTechModel());
209        input_to_ingress_link->setParameter("NumberBits", number_bits_per_flit);
210        input_to_ingress_link->setParameter("WireLayer", link_wire_layer);
211        input_to_ingress_link->setParameter("WireWidthMultiplier", link_wire_width_multiplier);
212        input_to_ingress_link->setParameter("WireSpacingMultiplier", link_wire_spacing_multiplier);
213        input_to_ingress_link->construct();
214        // Init ingress to middle link
215        ElectricalModel* ingress_to_middle_link = (ElectricalModel*)ModelGen::createModel("SWSRLink", "IngressToMiddleLink", getTechModel());
216        ingress_to_middle_link->setParameter("NumberBits", number_bits_per_flit);
217        ingress_to_middle_link->setParameter("CoreDataRate", clock_freq);
218        ingress_to_middle_link->setParameter("LinkDataRate", swsr_link_data_rate);
219        ingress_to_middle_link->setParameter("LaserType", swsr_laser_type);
220        ingress_to_middle_link->setParameter("RingTuningMethod", swsr_ring_tuning_method);
221        ingress_to_middle_link->construct();
222        // Init middle to egress link
223        ElectricalModel* middle_to_egress_link = (ElectricalModel*)ModelGen::createModel("SWSRLink", "MiddleToEgressLink", getTechModel());
224        middle_to_egress_link->setParameter("NumberBits", number_bits_per_flit);
225        middle_to_egress_link->setParameter("CoreDataRate", clock_freq);
226        middle_to_egress_link->setParameter("LinkDataRate", swsr_link_data_rate);
227        middle_to_egress_link->setParameter("LaserType", swsr_laser_type);
228        middle_to_egress_link->setParameter("RingTuningMethod", swsr_ring_tuning_method);
229        middle_to_egress_link->construct();
230        // Init egress to output link
231        ElectricalModel* egress_to_output_link = (ElectricalModel*)ModelGen::createModel("RepeatedLink", "EgressToOutputLink", getTechModel());
232        egress_to_output_link->setParameter("NumberBits", number_bits_per_flit);
233        egress_to_output_link->setParameter("WireLayer", link_wire_layer);
234        egress_to_output_link->setParameter("WireWidthMultiplier", link_wire_width_multiplier);
235        egress_to_output_link->setParameter("WireSpacingMultiplier", link_wire_spacing_multiplier);
236        egress_to_output_link->construct();
237
238        // Connect ports
239        createNet("InputToIngressLink_Out", makeNetIndex(0, number_bits_per_flit - 1));
240        createNet("InputToIngressLink_In", makeNetIndex(0, number_bits_per_flit - 1));
241        portConnect(input_to_ingress_link, "In", "InputToIngressLink_In");
242        portConnect(input_to_ingress_link, "Out", "InputToIngressLink_Out");
243
244        createNet("IngressToMiddleLink_In", makeNetIndex(0, number_bits_per_flit - 1));
245        createNet("IngressToMiddleLink_Out", makeNetIndex(0, number_bits_per_flit - 1));
246        portConnect(ingress_to_middle_link, "In", "IngressToMiddleLink_In");
247        portConnect(ingress_to_middle_link, "Out", "IngressToMiddleLink_Out");
248
249        createNet("MiddleToEgressLink_In", makeNetIndex(0, number_bits_per_flit - 1));
250        createNet("MiddleToEgressLink_Out", makeNetIndex(0, number_bits_per_flit - 1));
251        portConnect(middle_to_egress_link, "In", "MiddleToEgressLink_In");
252        portConnect(middle_to_egress_link, "Out", "MiddleToEgressLink_Out");
253
254        createNet("EgressToOutputLink_In", makeNetIndex(0, number_bits_per_flit - 1));
255        createNet("EgressToOutputLink_Out", makeNetIndex(0, number_bits_per_flit - 1));
256        portConnect(egress_to_output_link, "In", "EgressToOutputLink_In");
257        portConnect(egress_to_output_link, "Out", "EgressToOutputLink_Out");
258
259        portConnect(ingress_router, "CK", "CK");
260        for(unsigned int i = 0; i < ingress_router_number_input_ports; ++i)
261        {
262            createNet("IngressRouter_In" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
263            for (unsigned int j = 0; j < number_bits_per_flit; ++j)
264                assignVirtualFanout("IngressRouter_In" + (String)i, makeNetIndex(j), "InputToIngressLink_Out", makeNetIndex(j));
265            portConnect(ingress_router, "FlitIn" + (String)i, "IngressRouter_In" + (String)i);
266        }
267        for(unsigned int i = 0; i < ingress_router_number_output_ports; ++i)
268        {
269            // VFI
270            portConnect(ingress_router, "FlitOut" + (String)i, "IngressToMiddleLink_In");
271        }
272        portConnect(middle_router, "CK", "CK");
273        for(unsigned int i = 0; i < middle_router_number_input_ports; ++i)
274        {
275            createNet("MiddleRouter_In" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
276            for (unsigned int j = 0; j < number_bits_per_flit; ++j)
277                assignVirtualFanout("MiddleRouter_In" + (String)i, makeNetIndex(j), "IngressToMiddleLink_Out", makeNetIndex(j));
278            portConnect(middle_router, "FlitIn" + (String)i, "MiddleRouter_In" + (String)i);
279        }
280        for(unsigned int i = 0; i < middle_router_number_output_ports; ++i)
281        {
282            // VFI
283            portConnect(middle_router, "FlitOut" + (String)i, "MiddleToEgressLink_In");
284        }
285        portConnect(egress_router, "CK", "CK");
286        for(unsigned int i = 0; i < egress_router_number_input_ports; ++i)
287        {
288            createNet("EgressRouter_In" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
289            for (unsigned int j = 0; j < number_bits_per_flit; ++j)
290                assignVirtualFanout("EgressRouter_In" + (String)i, makeNetIndex(j), "MiddleToEgressLink_Out", makeNetIndex(j));
291            portConnect(egress_router, "FlitIn" + (String)i, "EgressRouter_In" + (String)i);
292        }
293        for(unsigned int i = 0; i < egress_router_number_output_ports; ++i)
294        {
295            // VFI
296            portConnect(egress_router, "FlitOut" + (String)i, "EgressToOutputLink_In");
297        }
298
299        // Create area, power, and event results
300        createElectricalResults();
301        createElectricalEventResult("AvgUnicast");
302        createElectricalEventResult("AvgBroadcast");
303        addNddPowerResult(new Result("Laser"));
304        addNddPowerResult(new Result("RingTuning"));
305        addAreaResult(new Result("Photonic"));
306
307        // Add all instances
308        addSubInstances(ingress_router, number_ingress_routers);
309        addElectricalSubResults(ingress_router, number_ingress_routers);
310        addSubInstances(middle_router, number_middle_routers);
311        addElectricalSubResults(middle_router, number_middle_routers);
312        addSubInstances(egress_router, number_egress_routers);
313        addElectricalSubResults(egress_router, number_egress_routers);
314        addSubInstances(input_to_ingress_link, number_input_to_ingress_links);
315        addElectricalSubResults(input_to_ingress_link, number_input_to_ingress_links);
316        addSubInstances(ingress_to_middle_link, number_ingress_to_middle_links);
317        addElectricalSubResults(ingress_to_middle_link, number_ingress_to_middle_links);
318        getAreaResult("Photonic")->addSubResult(ingress_to_middle_link->getAreaResult("Photonic"), "IngressToMiddleLink", number_ingress_to_middle_links);
319        getNddPowerResult("Laser")->addSubResult(ingress_to_middle_link->getNddPowerResult("Laser"), "IngressToMiddleLink", number_ingress_to_middle_links);
320        getNddPowerResult("RingTuning")->addSubResult(ingress_to_middle_link->getNddPowerResult("RingTuning"), "IngressToMiddleLink", number_ingress_to_middle_links);
321        addSubInstances(middle_to_egress_link, number_middle_to_egress_links);
322        addElectricalSubResults(middle_to_egress_link, number_middle_to_egress_links);
323        getAreaResult("Photonic")->addSubResult(middle_to_egress_link->getAreaResult("Photonic"), "MiddletoEgressLink", number_middle_to_egress_links);
324        getNddPowerResult("Laser")->addSubResult(middle_to_egress_link->getNddPowerResult("Laser"), "MiddleToEgressLink", number_middle_to_egress_links);
325        getNddPowerResult("RingTuning")->addSubResult(middle_to_egress_link->getNddPowerResult("RingTuning"), "MiddleToEgressLink", number_middle_to_egress_links);
326        addSubInstances(egress_to_output_link, number_egress_to_output_links);
327        addElectricalSubResults(egress_to_output_link, number_egress_to_output_links);
328
329        // Update unicast event
330        Result* avg_unicast_event = getEventResult("AvgUnicast");
331        avg_unicast_event->addSubResult(input_to_ingress_link->getEventResult("Send"), "InputToIngressLink", 1.0);
332        if(ingress_router->hasEventResult("WriteBuffer"))
333        {
334            avg_unicast_event->addSubResult(ingress_router->getEventResult("WriteBuffer"), "IngressRouter", 1.0);
335        }
336        if(ingress_router->hasEventResult("ReadBuffer"))
337        {
338            avg_unicast_event->addSubResult(ingress_router->getEventResult("ReadBuffer"), "IngressRouter", 1.0);
339        }
340        avg_unicast_event->addSubResult(ingress_router->getEventResult("TraverseCrossbar->Multicast1"), "IngressRouter", 1.0);
341        avg_unicast_event->addSubResult(ingress_to_middle_link->getEventResult("Send"), "IngressToMiddleLink", 1.0);
342        if(middle_router->hasEventResult("WriteBuffer"))
343        {
344            avg_unicast_event->addSubResult(middle_router->getEventResult("WriteBuffer"), "MiddleRouter", 1.0);
345        }
346        if(middle_router->hasEventResult("ReadBuffer"))
347        {
348            avg_unicast_event->addSubResult(middle_router->getEventResult("ReadBuffer"), "MiddleRouter", 1.0);
349        }
350        avg_unicast_event->addSubResult(middle_router->getEventResult("TraverseCrossbar->Multicast1"), "MiddleRouter", 1.0);
351        avg_unicast_event->addSubResult(middle_to_egress_link->getEventResult("Send"), "MiddleToEgressLink", 1.0);
352        if(egress_router->hasEventResult("WriteBuffer"))
353        {
354            avg_unicast_event->addSubResult(egress_router->getEventResult("WriteBuffer"), "EgressRouter", 1.0);
355        }
356        if(egress_router->hasEventResult("ReadBuffer"))
357        {
358            avg_unicast_event->addSubResult(egress_router->getEventResult("ReadBuffer"), "EgressRouter", 1.0);
359        }
360        avg_unicast_event->addSubResult(egress_router->getEventResult("TraverseCrossbar->Multicast1"), "EgressRouter", 1.0);
361        avg_unicast_event->addSubResult(egress_to_output_link->getEventResult("Send"), "EgressToOutputLink", 1.0);
362
363        // Update broadcast event
364        Result* avg_broadcast_event = getEventResult("AvgBroadcast");
365        avg_broadcast_event->addSubResult(input_to_ingress_link->getEventResult("Send"), "InputToIngressLink", 1.0);
366        if(ingress_router->hasEventResult("WriteBuffer"))
367        {
368            avg_broadcast_event->addSubResult(ingress_router->getEventResult("WriteBuffer"), "IngressRouter", 1.0);
369        }
370        if(ingress_router->hasEventResult("ReadBuffer"))
371        {
372            avg_broadcast_event->addSubResult(ingress_router->getEventResult("ReadBuffer"), "IngressRouter", 1.0);
373        }
374        avg_broadcast_event->addSubResult(ingress_router->getEventResult("TraverseCrossbar->Multicast1"), "IngressRouter", 1.0);
375        avg_broadcast_event->addSubResult(ingress_to_middle_link->getEventResult("Send"), "IngressToMiddleLink", 1.0);
376        if(middle_router->hasEventResult("WriteBuffer"))
377        {
378            avg_broadcast_event->addSubResult(middle_router->getEventResult("WriteBuffer"), "MiddleRouter", 1.0);
379        }
380        if(middle_router->hasEventResult("ReadBuffer"))
381        {
382            avg_broadcast_event->addSubResult(middle_router->getEventResult("ReadBuffer"), "MiddleRouter", 1.0);
383        }
384        avg_broadcast_event->addSubResult(middle_router->getEventResult("TraverseCrossbar->Multicast1"), "MiddleRouter", 1.0);
385        avg_broadcast_event->addSubResult(middle_to_egress_link->getEventResult("Send"), "MiddleToEgressLink", number_egress_routers);
386        if(egress_router->hasEventResult("WriteBuffer"))
387        {
388            avg_broadcast_event->addSubResult(egress_router->getEventResult("WriteBuffer"), "EgressRouter", number_egress_routers);
389        }
390        if(egress_router->hasEventResult("ReadBuffer"))
391        {
392            avg_broadcast_event->addSubResult(egress_router->getEventResult("ReadBuffer"), "EgressRouter", number_egress_routers);
393        }
394        avg_broadcast_event->addSubResult(egress_router->getEventResult("TraverseCrossbar->Multicast" + (String)number_egress_routers), "EgressRouter", 1.0);
395        avg_broadcast_event->addSubResult(egress_to_output_link->getEventResult("Send"), "EgressToOutputLink", number_output_sites);
396        return;
397    }
398
399    void PhotonicClos::updateModel()
400    {
401        // Assumes waveguide runs adjacent to ingress and egress routers
402        // Assumes input sites belonging to each ingress router are centered around the ingress router
403        // Assumes middle routers are distributed around the chip adjacent to the main waveguide
404        // Assumes output sites belonging to each egress router are centered around the egress router
405
406        // Get properties
407        double input_site_pitch = getProperty("InputSitePitch").toDouble();
408        double output_site_pitch = getProperty("OutputSitePitch").toDouble();
409        double clock_freq = getParameter("Frequency");
410		const double swsr_opt_util = getProperty("SWSR->OptUtil");
411
412        ASSERT(input_site_pitch > 0, "[Error] " + getInstanceName() +
413                " -> Input site pitch must be > 0!");
414        ASSERT(output_site_pitch > 0, "[Error] " + getInstanceName() +
415                " -> Output site pitch must be > 0!");
416
417        unsigned int number_input_sites_per_ingress_router = getGenProperties()->get("NumberInputSitesPerIngressRouter");
418        unsigned int number_ingress_routers = getParameter("NumberIngressRouters");
419        unsigned int number_output_sites_per_egress_router = getGenProperties()->get("NumberOutputSitesPerEgressRouter");
420        unsigned int number_egress_routers = getParameter("NumberEgressRouters");
421        double delay = 1.0 / clock_freq;
422
423        //Calculate the length of the waveguide
424        double input_to_ingress_link_length = input_site_pitch * (sqrt(number_input_sites_per_ingress_router) - 1.0);
425        double input_to_ingress_link_delay = delay * 0.8;
426        double ingress_to_middle_link_length = input_site_pitch * (sqrt(number_input_sites_per_ingress_router) * number_ingress_routers);
427        double middle_to_egress_link_length = output_site_pitch * (sqrt(number_output_sites_per_egress_router) * number_egress_routers);
428        double egress_to_output_link_length = output_site_pitch * (sqrt(number_output_sites_per_egress_router) - 1.0);
429        double egress_to_output_link_delay = delay * 0.8;
430        double ingress_router_delay = delay;
431        double middle_router_delay = delay;
432        double egress_router_delay = delay;
433
434        Model* input_to_ingress_link = getSubInstance("InputToIngressLink");
435        input_to_ingress_link->setProperty("WireLength", input_to_ingress_link_length);
436        input_to_ingress_link->setProperty("Delay", input_to_ingress_link_delay);
437        input_to_ingress_link->setProperty("IsKeepParity", "TRUE");
438        input_to_ingress_link->update();
439
440        Model* ingress_to_middle_link = getSubInstance("IngressToMiddleLink");
441        ingress_to_middle_link->setProperty("Length", ingress_to_middle_link_length);
442		ingress_to_middle_link->setProperty("OptUtil", swsr_opt_util);
443        ingress_to_middle_link->update();
444
445        Model* middle_to_egress_link = getSubInstance("MiddleToEgressLink");
446        middle_to_egress_link->setProperty("Length", middle_to_egress_link_length);
447		middle_to_egress_link->setProperty("OptUtil", swsr_opt_util);
448        middle_to_egress_link->update();
449
450        Model* egress_to_output_link = getSubInstance("EgressToOutputLink");
451        egress_to_output_link->setProperty("WireLength", egress_to_output_link_length);
452        egress_to_output_link->setProperty("Delay", egress_to_output_link_delay);
453        egress_to_output_link->setProperty("IsKeepParity", "TRUE");
454        egress_to_output_link->update();
455
456        ElectricalModel* ingress_router = (ElectricalModel*)getSubInstance("IngressRouter");
457        ingress_router->update();
458        ElectricalTimingTree ingress_router_timing_tree("IngressRouter", ingress_router);
459        ingress_router_timing_tree.performTimingOpt(ingress_router->getNet("CK"), ingress_router_delay);
460
461        ElectricalModel* middle_router = (ElectricalModel*)getSubInstance("MiddleRouter");
462        middle_router->update();
463        ElectricalTimingTree middle_router_timing_tree("MiddleRouter", middle_router);
464        middle_router_timing_tree.performTimingOpt(middle_router->getNet("CK"), middle_router_delay);
465
466        ElectricalModel* egress_router = (ElectricalModel*)getSubInstance("EgressRouter");
467        egress_router->update();
468        ElectricalTimingTree egress_router_timing_tree("EgressRouter", egress_router);
469        egress_router_timing_tree.performTimingOpt(egress_router->getNet("CK"), egress_router_delay);
470
471        return;
472    }
473
474    void PhotonicClos::propagateTransitionInfo()
475    {
476        // Get parameters
477        double clock_freq = getParameter("Frequency");
478        double swsr_link_data_rate = getParameter("SWSR->LinkDataRate");
479
480        // Get properties
481        unsigned int ingress_router_number_input_ports = getGenProperties()->get("IngressRouter->NumberInputPorts");
482        unsigned int middle_router_number_input_ports = getGenProperties()->get("MiddleRouter->NumberInputPorts");
483        unsigned int egress_router_number_input_ports = getGenProperties()->get("EgressRouter->NumberInputPorts");
484
485        ElectricalModel* input_to_ingress_link = (ElectricalModel*)getSubInstance("InputToIngressLink");
486        assignPortTransitionInfo(input_to_ingress_link, "In", TransitionInfo(0.25, 0.25, 0.25));
487        input_to_ingress_link->use();
488
489        ElectricalModel* ingress_to_middle_link = (ElectricalModel*)getSubInstance("IngressToMiddleLink");
490        assignPortTransitionInfo(ingress_to_middle_link, "LinkCK", TransitionInfo(0.0, (double) clock_freq / (swsr_link_data_rate * 2.0), 0.0));
491        assignPortTransitionInfo(ingress_to_middle_link, "In", TransitionInfo(0.25, 0.25, 0.25));
492        ingress_to_middle_link->use();
493
494        ElectricalModel* middle_to_egress_link = (ElectricalModel*)getSubInstance("MiddleToEgressLink");
495        assignPortTransitionInfo(middle_to_egress_link, "LinkCK", TransitionInfo(0.0, (double) clock_freq / (swsr_link_data_rate * 2.0), 0.0));
496        assignPortTransitionInfo(middle_to_egress_link, "In", TransitionInfo(0.25, 0.25, 0.25));
497        middle_to_egress_link->use();
498
499        ElectricalModel* egress_to_output_link = (ElectricalModel*)getSubInstance("EgressToOutputLink");
500        assignPortTransitionInfo(egress_to_output_link, "In", TransitionInfo(0.25, 0.25, 0.25));
501        egress_to_output_link->use();
502
503        ElectricalModel* ingress_router = (ElectricalModel*)getSubInstance("IngressRouter");
504        for(unsigned int i = 0; i < ingress_router_number_input_ports; ++i)
505        {
506            assignPortTransitionInfo(ingress_router, "FlitIn" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
507        }
508        assignPortTransitionInfo(ingress_router, "CK", TransitionInfo(0.0, 1.0, 0.0));
509        ingress_router->getGenProperties()->set("UseModelEvent", "");
510        ingress_router->use();
511
512        ElectricalModel* middle_router = (ElectricalModel*)getSubInstance("MiddleRouter");
513        for(unsigned int i = 0; i < middle_router_number_input_ports; ++i)
514        {
515            assignPortTransitionInfo(middle_router, "FlitIn" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
516        }
517        assignPortTransitionInfo(middle_router, "CK", TransitionInfo(0.0, 1.0, 0.0));
518        middle_router->getGenProperties()->set("UseModelEvent", "");
519        middle_router->use();
520
521        ElectricalModel* egress_router = (ElectricalModel*)getSubInstance("EgressRouter");
522        for(unsigned int i = 0; i < egress_router_number_input_ports; ++i)
523        {
524            assignPortTransitionInfo(egress_router, "FlitIn" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
525        }
526        assignPortTransitionInfo(egress_router, "CK", TransitionInfo(0.0, 1.0, 0.0));
527        egress_router->getGenProperties()->set("UseModelEvent", "");
528        egress_router->use();
529
530        return;
531    }
532} // namespace DSENT
533
534