Router.cc revision 10447:a465576671d4
1#include "model/electrical/router/Router.h"
2
3#include <cmath>
4#include <vector>
5
6#include "model/PortInfo.h"
7#include "model/EventInfo.h"
8#include "model/TransitionInfo.h"
9#include "model/ModelGen.h"
10#include "model/std_cells/StdCellLib.h"
11#include "model/std_cells/StdCell.h"
12#include "model/electrical/router/RouterInputPort.h"
13#include "model/electrical/router/RouterSwitchAllocator.h"
14#include "model/timing_graph/ElectricalNet.h"
15
16namespace DSENT
17{
18    using std::sqrt;
19    using std::vector;
20
21    using LibUtil::castStringVector;
22    using LibUtil::vectorToString;
23
24    Router::Router(const String& instance_name_, const TechModel* tech_model_)
25        : ElectricalModel(instance_name_, tech_model_)
26    {
27        initParameters();
28        initProperties();
29    }
30
31    Router::~Router()
32    {}
33
34    void Router::initParameters()
35    {
36        addParameterName("NumberInputPorts");
37        addParameterName("NumberOutputPorts");
38        addParameterName("NumberBitsPerFlit");
39        addParameterName("NumberVirtualNetworks");
40        addParameterName("NumberVirtualChannelsPerVirtualNetwork");
41        addParameterName("NumberBuffersPerVirtualChannel");
42        // Spec for input port
43        addParameterName("InputPort->BufferModel");
44        // Spec for crossbar
45        addParameterName("CrossbarModel");
46        // Spec for switch allocator
47        addParameterName("SwitchAllocator->ArbiterModel");
48        // Spec for clock tree
49        addParameterName("ClockTreeModel");
50        addParameterName("ClockTree->NumberLevels");
51        addParameterName("ClockTree->WireLayer");
52        addParameterName("ClockTree->WireWidthMultiplier");
53        addParameterName("ClockTree->WireSpacingMultiplier", 3.0);
54        return;
55    }
56
57    void Router::initProperties()
58    {
59        return;
60    }
61
62    Router* Router::clone() const
63    {
64        // TODO
65        return NULL;
66    }
67
68    void Router::constructModel()
69    {
70        // Get parameters
71        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
72        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
73        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
74
75        ASSERT(number_input_ports > 0, "[Error] " + getInstanceName() +
76                " -> Number of input ports must be > 0!");
77        ASSERT(number_output_ports > 0, "[Error] " + getInstanceName() +
78                " -> Number of output ports must be > 0!");
79        ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() +
80                " -> Number of bits per buffer must be > 0!");
81
82        // Create ports
83        createInputPort("CK");
84        for(unsigned int i = 0; i < number_input_ports; ++i)
85        {
86            createInputPort("FlitIn" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
87        }
88        for(unsigned int i = 0; i < number_output_ports; ++i)
89        {
90            createOutputPort("FlitOut" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
91        }
92
93        // Create area, power, event results
94        createElectricalResults();
95        getEventInfo("Idle")->setStaticTransitionInfos();
96        getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
97
98        createElectricalEventResult("ReadBuffer");
99        getEventInfo("ReadBuffer")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
100        createElectricalEventResult("WriteBuffer");
101        getEventInfo("WriteBuffer")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
102        for(unsigned int i = 1; i <= number_output_ports; ++i)
103        {
104            createElectricalEventResult("TraverseCrossbar->Multicast" + (String)i);
105            getEventInfo("TraverseCrossbar->Multicast" + (String)i)->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
106        }
107        createElectricalEventResult("ArbitrateSwitch->ArbitrateStage1");
108        createElectricalEventResult("ArbitrateSwitch->ArbitrateStage2");
109        createElectricalEventResult("DistributeClock");
110        getEventInfo("DistributeClock")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
111
112        // Create intermediate nets
113        createNet("PipelineReg0_In");
114        createNet("PipelineReg0_Out");
115        createNet("PipelineReg1_In");
116        createNet("PipelineReg1_Out");
117        for(unsigned int i = 0; i < number_output_ports; ++i)
118        {
119            createNet("PipelineReg2_In" + (String)i);
120            createNet("PipelineReg2_Out" + (String)i);
121        }
122
123        createRouterInputPort();
124        createSwitchAllocator();
125        createVirtualChannelAllocator();
126        createCrossbar();
127        createClockTree();
128        createPipelineReg();
129
130        // Get generated numbers
131        unsigned int number_crossbar_selects = getGenProperties()->get("Crossbar->NumberSelects");
132
133        // Add write buffer event
134        getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("DFFD"), "PipelineReg0", number_bits_per_flit);
135        getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("DFFQ"), "PipelineReg0", number_bits_per_flit);
136        getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("CK"), "PipelineReg0", number_bits_per_flit);
137        getEventResult("WriteBuffer")->addSubResult(getSubInstance("InputPort")->getEventResult("WriteBuffer"), "InputPort", 1.0);
138
139        // Add read buffer event
140        getEventResult("ReadBuffer")->addSubResult(getSubInstance("InputPort")->getEventResult("ReadBuffer"), "InputPort", 1.0);
141        getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("DFFD"), "PipelineReg1", number_bits_per_flit);
142        getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("DFFQ"), "PipelineReg1", number_bits_per_flit);
143        getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("CK"), "PipelineReg1", number_bits_per_flit);
144
145        // Add crossbar traversal event
146        for(unsigned int i = 1; i <= number_output_ports; ++i)
147        {
148            Result* traverse_crossbar_event = getEventResult("TraverseCrossbar->Multicast" + (String)i);
149            traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("DFFD"), "Crossbar_Sel_DFF", number_crossbar_selects);
150            traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("DFFQ"), "Crossbar_Sel_DFF", number_crossbar_selects);
151            traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("CK"), "Crossbar_Sel_DFF", number_crossbar_selects);
152            traverse_crossbar_event->addSubResult(getSubInstance("Crossbar")->getEventResult("Multicast" + (String)i), "Crossbar", 1.0);
153            for(unsigned int j = 0; j < i; ++j)
154            {
155                traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("DFFD"), "PipelineReg2_" + (String)j, number_bits_per_flit);
156                traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("DFFQ"), "PipelineReg2_" + (String)j, number_bits_per_flit);
157                traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("CK"), "PipelineReg2_" + (String)j, number_bits_per_flit);
158            }
159        }
160
161        // Add stage1 allocator arbitrate
162        Result* arb_sw_stage1_event = getEventResult("ArbitrateSwitch->ArbitrateStage1");
163        arb_sw_stage1_event->addSubResult(getSubInstance("SwitchAllocator")->getEventResult("ArbitrateStage1"), "SwitchAllocator", 1.0);
164
165        // Add stage2 allocator arbitrate
166        Result* arb_sw_stage2_event = getEventResult("ArbitrateSwitch->ArbitrateStage2");
167        arb_sw_stage2_event->addSubResult(getSubInstance("SwitchAllocator")->getEventResult("ArbitrateStage2"), "SwitchAllocator", 1.0);
168
169        // Add CK event
170        getEventResult("DistributeClock")->addSubResult(getSubInstance("ClockTree")->getEventResult("Send"), "ClockTree", 1.0);
171        return;
172    }
173
174    void Router::updateModel()
175    {
176        // Get parameters
177        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
178
179        // Update other components
180        getSubInstance("PipelineReg0")->update();
181        getSubInstance("InputPort")->update();
182        getSubInstance("PipelineReg1")->update();
183        getSubInstance("Crossbar_Sel_DFF")->update();
184        getSubInstance("Crossbar")->update();
185        for(unsigned int i = 0; i < number_output_ports; ++i)
186        {
187            getSubInstance("PipelineReg2_" + (String)i)->update();
188        }
189        getSubInstance("SwitchAllocator")->update();
190
191        // Update clock tree
192        double total_clock_tree_cap = getNet("CK")->getTotalDownstreamCap();
193        double router_area = getAreaResult("Active")->calculateSum();
194        Model* clock_tree = getSubInstance("ClockTree");
195        clock_tree->setProperty("SitePitch", sqrt(router_area));
196        clock_tree->setProperty("TotalLoadCapPerBit", total_clock_tree_cap);
197        clock_tree->update();
198
199        return;
200    }
201
202    void Router::propagateTransitionInfo()
203    {
204        // Update probability
205        unsigned int number_output_ports = getParameter("NumberOutputPorts");
206
207        // Current event
208        const String& current_event = getGenProperties()->get("UseModelEvent");
209
210        ElectricalModel* pipeline_reg0 = (ElectricalModel*)getSubInstance("PipelineReg0");
211        propagatePortTransitionInfo(pipeline_reg0, "D", "FlitIn0");
212        propagatePortTransitionInfo(pipeline_reg0, "CK", "CK");
213        pipeline_reg0->use();
214
215        ElectricalModel* input_port = (ElectricalModel*)getSubInstance("InputPort");
216        propagatePortTransitionInfo(input_port, "FlitIn", pipeline_reg0, "Q");
217        propagatePortTransitionInfo(input_port, "CK", "CK");
218        input_port->getGenProperties()->set("UseModelEvent", "ReadWrite");
219        input_port->use();
220
221        ElectricalModel* pipeline_reg1 = (ElectricalModel*)getSubInstance("PipelineReg1");
222        propagatePortTransitionInfo(pipeline_reg1, "D", "FlitIn0");
223        propagatePortTransitionInfo(pipeline_reg1, "CK", "CK");
224        pipeline_reg1->use();
225
226        ElectricalModel* crossbar_sel_dff = (ElectricalModel*)getSubInstance("Crossbar_Sel_DFF");
227        assignPortTransitionInfo(crossbar_sel_dff, "D", TransitionInfo());
228        propagatePortTransitionInfo(crossbar_sel_dff, "CK", "CK");
229        crossbar_sel_dff->use();
230
231        ElectricalModel* crossbar = (ElectricalModel*)getSubInstance("Crossbar");
232        bool is_crossbar_event = false;
233        for(unsigned int i = 1; i <= number_output_ports; ++i)
234        {
235            if(current_event == ("TraverseCrossbar->Multicast" + (String)i))
236            {
237                is_crossbar_event = true;
238                // Assume the flit is sent from port 0 to port 0~i-1
239                // Apply default transition info
240                crossbar->applyTransitionInfo("Multicast" + (String)i);
241                // Overwrite transition info
242                propagatePortTransitionInfo(crossbar, "In0", "FlitIn0");
243                break;
244            }
245        }
246        if(is_crossbar_event == false)
247        {
248            crossbar->applyTransitionInfo("Multicast1");
249            propagatePortTransitionInfo(crossbar, "In0", "FlitIn0");
250        }
251        crossbar->use();
252
253        vector<ElectricalModel*> pipeline_reg2s(number_output_ports, NULL);
254        for(unsigned int i = 0; i < number_output_ports; ++i)
255        {
256            pipeline_reg2s[i] = (ElectricalModel*)getSubInstance("PipelineReg2_" + (String)i);
257            propagatePortTransitionInfo(pipeline_reg2s[i], "D", "FlitIn0");
258            propagatePortTransitionInfo(pipeline_reg2s[i], "CK", "CK");
259            pipeline_reg2s[i]->use();
260        }
261
262        ElectricalModel* sw_allocator = (ElectricalModel*)getSubInstance("SwitchAllocator");
263        if(current_event == "ArbitrateSwitch->ArbitrateStage1")
264        {
265            sw_allocator->applyTransitionInfo("ArbitrateStage1");
266        }
267        else if(current_event == "ArbitrateSwitch->ArbitrateStage2")
268        {
269            sw_allocator->applyTransitionInfo("ArbitrateStage2");
270        }
271        else
272        {
273            sw_allocator->applyTransitionInfo("Idle");
274        }
275        sw_allocator->use();
276
277        ElectricalModel* clock_tree = (ElectricalModel*)getSubInstance("ClockTree");
278        propagatePortTransitionInfo(clock_tree, "In", "CK");
279        clock_tree->use();
280        return;
281    }
282
283    void Router::createRouterInputPort()
284    {
285        // Get parameters
286        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
287        unsigned int number_vns = getParameter("NumberVirtualNetworks").toUInt();
288        const String& number_vcs_per_vn = getParameter("NumberVirtualChannelsPerVirtualNetwork");
289        const String& number_bufs_per_vc = getParameter("NumberBuffersPerVirtualChannel");
290        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
291        const String& buffer_model = getParameter("InputPort->BufferModel");
292
293        // Init input port model
294        const String& input_port_name = "InputPort";
295        RouterInputPort* input_port = new RouterInputPort(input_port_name, getTechModel());
296        input_port->setParameter("NumberVirtualNetworks", number_vns);
297        input_port->setParameter("NumberVirtualChannelsPerVirtualNetwork", number_vcs_per_vn);
298        input_port->setParameter("NumberBuffersPerVirtualChannel", number_bufs_per_vc);
299        input_port->setParameter("NumberBitsPerFlit", number_bits_per_flit);
300        input_port->setParameter("BufferModel", buffer_model);
301        input_port->construct();
302
303        unsigned int number_input_port_outputs = input_port->getGenProperties()->get("NumberOutputs");
304        unsigned int number_input_port_addr_bits = input_port->getGenProperties()->get("NumberAddressBits");
305        getGenProperties()->set("InputPort->NumberOutputs", number_input_port_outputs);
306        getGenProperties()->set("InputPort->NumberAddressBits", number_input_port_addr_bits);
307
308        unsigned int total_number_vcs = input_port->getGenProperties()->get("TotalNumberVirtualChannels");
309        getGenProperties()->set("TotalNumberVirtualChannels", total_number_vcs);
310
311        // Add the instance and the results
312        addSubInstances(input_port, number_input_ports);
313        addElectricalSubResults(input_port, number_input_ports);
314
315        // Create connections
316        createNet("InputPort_In", makeNetIndex(0, number_bits_per_flit-1));
317        createNet("InputPort_Out", makeNetIndex(0, number_bits_per_flit-1));
318
319        assignVirtualFanout("InputPort_In", "PipelineReg0_Out");
320        portConnect(input_port, "FlitIn", "InputPort_In");
321        portConnect(input_port, "CK", "CK");
322        portConnect(input_port, "FlitOut", "InputPort_Out");
323        assignVirtualFanin("PipelineReg1_In", "InputPort_Out");
324
325        return;
326    }
327
328    void Router::createVirtualChannelAllocator()
329    {}
330
331    void Router::createSwitchAllocator()
332    {
333        // Get parameters
334        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
335        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
336        unsigned int total_number_vcs = getGenProperties()->get("TotalNumberVirtualChannels").toUInt();
337        const String& arb_model = getParameter("SwitchAllocator->ArbiterModel");
338
339        // Init switch allocator model
340        const String& sw_allocator_name = "SwitchAllocator";
341        RouterSwitchAllocator* sw_allocator = new RouterSwitchAllocator(sw_allocator_name, getTechModel());
342        sw_allocator->setParameter("NumberInputPorts", number_input_ports);
343        sw_allocator->setParameter("NumberOutputPorts", number_output_ports);
344        sw_allocator->setParameter("TotalNumberVirtualChannels", total_number_vcs);
345        sw_allocator->setParameter("ArbiterModel", arb_model);
346        sw_allocator->construct();
347
348        // Add the instance and the results
349        addSubInstances(sw_allocator, 1.0);
350        addElectricalSubResults(sw_allocator, 1.0);
351
352        // Create connections (currently connect CK only)
353        portConnect(sw_allocator, "CK", "CK");
354        return;
355    }
356
357    void Router::createCrossbar()
358    {
359        // Get parameters
360        const String& crossbar_model = getParameter("CrossbarModel");
361        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
362        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
363        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
364        unsigned int number_input_port_outputs = getGenProperties()->get("InputPort->NumberOutputs").toUInt();
365
366        unsigned int number_crossbar_inputs = number_input_port_outputs * number_input_ports;
367        unsigned int number_crossbar_outputs = number_output_ports;
368        getGenProperties()->set("Crossbar->NumberInputs", number_crossbar_inputs);
369        getGenProperties()->set("Crossbar->NumberOutputs", number_crossbar_outputs);
370
371        // Init crossbar model
372        const String& crossbar_name = "Crossbar";
373        ElectricalModel* crossbar = ModelGen::createCrossbar(crossbar_model, crossbar_name, getTechModel());
374        crossbar->setParameter("NumberInputs", number_crossbar_inputs);
375        crossbar->setParameter("NumberOutputs", number_crossbar_outputs);
376        crossbar->setParameter("NumberBits", number_bits_per_flit);
377        crossbar->setParameter("BitDuplicate", "TRUE");
378        crossbar->construct();
379
380        unsigned int number_crossbar_selects = crossbar->getGenProperties()->get("NumberSelectsPerPort");
381        getGenProperties()->set("Crossbar->NumberSelects", number_crossbar_selects);
382
383        // Init DFF for crossbar selections
384        const String& crossbar_sel_dff_name = "Crossbar_Sel_DFF";
385        StdCell* crossbar_sel_dff = getTechModel()->getStdCellLib()->createStdCell("DFFQ", crossbar_sel_dff_name);
386        crossbar_sel_dff->construct();
387
388        // Add instances and results
389        addSubInstances(crossbar, 1.0);
390        addElectricalSubResults(crossbar, 1.0);
391
392        addSubInstances(crossbar_sel_dff, number_crossbar_outputs * number_crossbar_selects);
393        addElectricalSubResults(crossbar_sel_dff, number_crossbar_outputs * number_crossbar_selects);
394
395        // Create connections
396        createNet("Crossbar_Sel_DFF_Out");
397        for(unsigned int i = 0; i < number_crossbar_outputs; ++i)
398        {
399            for(unsigned int j = 0; j < number_crossbar_selects; ++j)
400            {
401                createNet(String::format("Crossbar_Sel%d_%d", i, j));
402            }
403            createNet("Crossbar_Out" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
404        }
405        for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
406        {
407            createNet("Crossbar_In" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
408        }
409
410        for(unsigned int i = 0; i < number_crossbar_selects; ++i)
411        {
412            portConnect(crossbar_sel_dff, "CK", "CK");
413        }
414        portConnect(crossbar_sel_dff, "Q", "Crossbar_Sel_DFF_Out");
415        for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
416        {
417            assignVirtualFanout("Crossbar_In" + (String)i, "PipelineReg1_Out");
418            portConnect(crossbar, "In" + (String)i, "Crossbar_In" + (String)i);
419        }
420        for(unsigned int i = 0; i < number_crossbar_outputs; ++i)
421        {
422            for(unsigned int j = 0; j < number_crossbar_selects; ++j)
423            {
424                assignVirtualFanout(String::format("Crossbar_Sel%d_%d", i, j), "Crossbar_Sel_DFF_Out");
425                portConnect(crossbar, String::format("Sel%d_%d", i, j), String::format("Crossbar_Sel%d_%d", i, j));
426            }
427            portConnect(crossbar, "Out" + (String)i, "Crossbar_Out" + (String)i);
428            assignVirtualFanin("PipelineReg2_In" + (String)i, "Crossbar_Out" + (String)i);
429        }
430
431        return;
432    }
433
434    void Router::createPipelineReg()
435    {
436        // Get parameters
437        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
438        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
439        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
440        unsigned int number_crossbar_inputs = getGenProperties()->get("Crossbar->NumberInputs");
441
442        // Init pipeline reg model
443        // First stage: from router input to input port
444        const String& pipeline_reg0_name = "PipelineReg0";
445        StdCell* pipeline_reg0 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg0_name);
446        pipeline_reg0->construct();
447        // Second stage: from input port to crossbar
448        const String& pipeline_reg1_name = "PipelineReg1";
449        StdCell* pipeline_reg1 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg1_name);
450        pipeline_reg1->construct();
451
452        // Third stage: from crossbar to router output
453        vector<StdCell*> pipeline_reg2s(number_output_ports, (StdCell*)NULL);
454        vector<String> pipeline_reg2_names(number_output_ports, "");
455        for(unsigned int i = 0; i < number_output_ports; ++i)
456        {
457            pipeline_reg2_names[i] = "PipelineReg2_" + (String)i;
458            pipeline_reg2s[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg2_names[i]);
459            pipeline_reg2s[i]->construct();
460        }
461
462        // Add instances and results
463        addSubInstances(pipeline_reg0, number_input_ports * number_bits_per_flit);
464        addElectricalSubResults(pipeline_reg0, number_input_ports * number_bits_per_flit);
465
466        addSubInstances(pipeline_reg1, number_crossbar_inputs * number_bits_per_flit);
467        addElectricalSubResults(pipeline_reg1, number_crossbar_inputs * number_bits_per_flit);
468
469        for(unsigned int i = 0; i < number_output_ports; ++i)
470        {
471            addSubInstances(pipeline_reg2s[i], number_bits_per_flit);
472            addElectricalSubResults(pipeline_reg2s[i], number_bits_per_flit);
473        }
474
475        // Create data connections
476        for(unsigned int i = 0; i < number_input_ports; ++i)
477        {
478            assignVirtualFanin("PipelineReg0_In", "FlitIn" + (String)i);
479        }
480        portConnect(pipeline_reg0, "D", "PipelineReg0_In");
481        portConnect(pipeline_reg0, "Q", "PipelineReg0_Out");
482        portConnect(pipeline_reg1, "D", "PipelineReg1_In");
483        portConnect(pipeline_reg1, "Q", "PipelineReg1_Out");
484        for(unsigned int i = 0; i < number_output_ports; ++i)
485        {
486            portConnect(pipeline_reg2s[i], "D", "PipelineReg2_In" + (String)i);
487            portConnect(pipeline_reg2s[i], "Q", "PipelineReg2_Out" + (String)i);
488            assignVirtualFanout("FlitOut" + (String)i, "PipelineReg2_Out" + (String)i);
489        }
490
491        // Create CK connections
492        for(unsigned int n = 0; n < number_bits_per_flit; ++n)
493        {
494            for(unsigned int i = 0; i < number_input_ports; ++i)
495            {
496                portConnect(pipeline_reg0, "CK", "CK");
497            }
498            for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
499            {
500                portConnect(pipeline_reg1, "CK", "CK");
501            }
502            for(unsigned int i = 0; i < number_output_ports; ++i)
503            {
504                portConnect(pipeline_reg2s[i], "CK", "CK");
505            }
506        }
507        return;
508    }
509
510    void Router::createClockTree()
511    {
512        // Get parameters
513        const String& clock_tree_model = getParameter("ClockTreeModel");
514        const String& clock_tree_number_levels = getParameter("ClockTree->NumberLevels");
515        const String& clock_tree_wire_layer = getParameter("ClockTree->WireLayer");
516        const String& clock_tree_wire_width_multiplier = getParameter("ClockTree->WireWidthMultiplier");
517        const String& clock_tree_wire_spacing_multiplier = getParameter("ClockTree->WireSpacingMultiplier");
518
519        // Init clock tree model
520        const String& clock_tree_name = "ClockTree";
521        ElectricalModel* clock_tree = (ElectricalModel*)ModelGen::createModel(clock_tree_model, clock_tree_name, getTechModel());
522        clock_tree->setParameter("NumberLevels", clock_tree_number_levels);
523        clock_tree->setParameter("NumberBits", 1);
524        clock_tree->setParameter("WireLayer", clock_tree_wire_layer);
525        clock_tree->setParameter("WireWidthMultiplier", clock_tree_wire_width_multiplier);
526        clock_tree->setParameter("WireSpacingMultiplier", clock_tree_wire_spacing_multiplier);
527        clock_tree->construct();
528
529        // Add instances and results
530        addSubInstances(clock_tree, 1.0);
531        addElectricalSubResults(clock_tree, 1.0);
532
533        return;
534    }
535} // namespace DSENT
536
537