110448Snilay@cs.wisc.edu/* Copyright (c) 2012 Massachusetts Institute of Technology
210448Snilay@cs.wisc.edu *
310448Snilay@cs.wisc.edu * Permission is hereby granted, free of charge, to any person obtaining a copy
410448Snilay@cs.wisc.edu * of this software and associated documentation files (the "Software"), to deal
510448Snilay@cs.wisc.edu * in the Software without restriction, including without limitation the rights
610448Snilay@cs.wisc.edu * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
710448Snilay@cs.wisc.edu * copies of the Software, and to permit persons to whom the Software is
810448Snilay@cs.wisc.edu * furnished to do so, subject to the following conditions:
910448Snilay@cs.wisc.edu *
1010448Snilay@cs.wisc.edu * The above copyright notice and this permission notice shall be included in
1110448Snilay@cs.wisc.edu * all copies or substantial portions of the Software.
1210448Snilay@cs.wisc.edu *
1310448Snilay@cs.wisc.edu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1410448Snilay@cs.wisc.edu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1510448Snilay@cs.wisc.edu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1610448Snilay@cs.wisc.edu * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1710448Snilay@cs.wisc.edu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1810448Snilay@cs.wisc.edu * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1910448Snilay@cs.wisc.edu * THE SOFTWARE.
2010448Snilay@cs.wisc.edu */
2110448Snilay@cs.wisc.edu
2210447Snilay@cs.wisc.edu#include "model/electrical/router/Router.h"
2310447Snilay@cs.wisc.edu
2410447Snilay@cs.wisc.edu#include <cmath>
2510447Snilay@cs.wisc.edu#include <vector>
2610447Snilay@cs.wisc.edu
2710447Snilay@cs.wisc.edu#include "model/PortInfo.h"
2810447Snilay@cs.wisc.edu#include "model/EventInfo.h"
2910447Snilay@cs.wisc.edu#include "model/TransitionInfo.h"
3010447Snilay@cs.wisc.edu#include "model/ModelGen.h"
3110447Snilay@cs.wisc.edu#include "model/std_cells/StdCellLib.h"
3210447Snilay@cs.wisc.edu#include "model/std_cells/StdCell.h"
3310447Snilay@cs.wisc.edu#include "model/electrical/router/RouterInputPort.h"
3410447Snilay@cs.wisc.edu#include "model/electrical/router/RouterSwitchAllocator.h"
3510447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalNet.h"
3610447Snilay@cs.wisc.edu
3710447Snilay@cs.wisc.edunamespace DSENT
3810447Snilay@cs.wisc.edu{
3910447Snilay@cs.wisc.edu    using std::sqrt;
4010447Snilay@cs.wisc.edu    using std::vector;
4110447Snilay@cs.wisc.edu
4210447Snilay@cs.wisc.edu    using LibUtil::castStringVector;
4310447Snilay@cs.wisc.edu    using LibUtil::vectorToString;
4410447Snilay@cs.wisc.edu
4510447Snilay@cs.wisc.edu    Router::Router(const String& instance_name_, const TechModel* tech_model_)
4610447Snilay@cs.wisc.edu        : ElectricalModel(instance_name_, tech_model_)
4710447Snilay@cs.wisc.edu    {
4810447Snilay@cs.wisc.edu        initParameters();
4910447Snilay@cs.wisc.edu        initProperties();
5010447Snilay@cs.wisc.edu    }
5110447Snilay@cs.wisc.edu
5210447Snilay@cs.wisc.edu    Router::~Router()
5310447Snilay@cs.wisc.edu    {}
5410447Snilay@cs.wisc.edu
5510447Snilay@cs.wisc.edu    void Router::initParameters()
5610447Snilay@cs.wisc.edu    {
5710447Snilay@cs.wisc.edu        addParameterName("NumberInputPorts");
5810447Snilay@cs.wisc.edu        addParameterName("NumberOutputPorts");
5910447Snilay@cs.wisc.edu        addParameterName("NumberBitsPerFlit");
6010447Snilay@cs.wisc.edu        addParameterName("NumberVirtualNetworks");
6110447Snilay@cs.wisc.edu        addParameterName("NumberVirtualChannelsPerVirtualNetwork");
6210447Snilay@cs.wisc.edu        addParameterName("NumberBuffersPerVirtualChannel");
6310447Snilay@cs.wisc.edu        // Spec for input port
6410447Snilay@cs.wisc.edu        addParameterName("InputPort->BufferModel");
6510447Snilay@cs.wisc.edu        // Spec for crossbar
6610447Snilay@cs.wisc.edu        addParameterName("CrossbarModel");
6710447Snilay@cs.wisc.edu        // Spec for switch allocator
6810447Snilay@cs.wisc.edu        addParameterName("SwitchAllocator->ArbiterModel");
6910447Snilay@cs.wisc.edu        // Spec for clock tree
7010447Snilay@cs.wisc.edu        addParameterName("ClockTreeModel");
7110447Snilay@cs.wisc.edu        addParameterName("ClockTree->NumberLevels");
7210447Snilay@cs.wisc.edu        addParameterName("ClockTree->WireLayer");
7310447Snilay@cs.wisc.edu        addParameterName("ClockTree->WireWidthMultiplier");
7410447Snilay@cs.wisc.edu        addParameterName("ClockTree->WireSpacingMultiplier", 3.0);
7510447Snilay@cs.wisc.edu        return;
7610447Snilay@cs.wisc.edu    }
7710447Snilay@cs.wisc.edu
7810447Snilay@cs.wisc.edu    void Router::initProperties()
7910447Snilay@cs.wisc.edu    {
8010447Snilay@cs.wisc.edu        return;
8110447Snilay@cs.wisc.edu    }
8210447Snilay@cs.wisc.edu
8310447Snilay@cs.wisc.edu    Router* Router::clone() const
8410447Snilay@cs.wisc.edu    {
8510447Snilay@cs.wisc.edu        // TODO
8610447Snilay@cs.wisc.edu        return NULL;
8710447Snilay@cs.wisc.edu    }
8810447Snilay@cs.wisc.edu
8910447Snilay@cs.wisc.edu    void Router::constructModel()
9010447Snilay@cs.wisc.edu    {
9110447Snilay@cs.wisc.edu        // Get parameters
9210447Snilay@cs.wisc.edu        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
9310447Snilay@cs.wisc.edu        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
9410447Snilay@cs.wisc.edu        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
9510447Snilay@cs.wisc.edu
9610447Snilay@cs.wisc.edu        ASSERT(number_input_ports > 0, "[Error] " + getInstanceName() +
9710447Snilay@cs.wisc.edu                " -> Number of input ports must be > 0!");
9810447Snilay@cs.wisc.edu        ASSERT(number_output_ports > 0, "[Error] " + getInstanceName() +
9910447Snilay@cs.wisc.edu                " -> Number of output ports must be > 0!");
10010447Snilay@cs.wisc.edu        ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() +
10110447Snilay@cs.wisc.edu                " -> Number of bits per buffer must be > 0!");
10210447Snilay@cs.wisc.edu
10310447Snilay@cs.wisc.edu        // Create ports
10410447Snilay@cs.wisc.edu        createInputPort("CK");
10510447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_input_ports; ++i)
10610447Snilay@cs.wisc.edu        {
10710447Snilay@cs.wisc.edu            createInputPort("FlitIn" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
10810447Snilay@cs.wisc.edu        }
10910447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_output_ports; ++i)
11010447Snilay@cs.wisc.edu        {
11110447Snilay@cs.wisc.edu            createOutputPort("FlitOut" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
11210447Snilay@cs.wisc.edu        }
11310447Snilay@cs.wisc.edu
11410447Snilay@cs.wisc.edu        // Create area, power, event results
11510447Snilay@cs.wisc.edu        createElectricalResults();
11610447Snilay@cs.wisc.edu        getEventInfo("Idle")->setStaticTransitionInfos();
11710447Snilay@cs.wisc.edu        getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
11810447Snilay@cs.wisc.edu
11910447Snilay@cs.wisc.edu        createElectricalEventResult("ReadBuffer");
12010447Snilay@cs.wisc.edu        getEventInfo("ReadBuffer")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
12110447Snilay@cs.wisc.edu        createElectricalEventResult("WriteBuffer");
12210447Snilay@cs.wisc.edu        getEventInfo("WriteBuffer")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
12310447Snilay@cs.wisc.edu        for(unsigned int i = 1; i <= number_output_ports; ++i)
12410447Snilay@cs.wisc.edu        {
12510447Snilay@cs.wisc.edu            createElectricalEventResult("TraverseCrossbar->Multicast" + (String)i);
12610447Snilay@cs.wisc.edu            getEventInfo("TraverseCrossbar->Multicast" + (String)i)->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
12710447Snilay@cs.wisc.edu        }
12810447Snilay@cs.wisc.edu        createElectricalEventResult("ArbitrateSwitch->ArbitrateStage1");
12910447Snilay@cs.wisc.edu        createElectricalEventResult("ArbitrateSwitch->ArbitrateStage2");
13010447Snilay@cs.wisc.edu        createElectricalEventResult("DistributeClock");
13110447Snilay@cs.wisc.edu        getEventInfo("DistributeClock")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
13210447Snilay@cs.wisc.edu
13310447Snilay@cs.wisc.edu        // Create intermediate nets
13410447Snilay@cs.wisc.edu        createNet("PipelineReg0_In");
13510447Snilay@cs.wisc.edu        createNet("PipelineReg0_Out");
13610447Snilay@cs.wisc.edu        createNet("PipelineReg1_In");
13710447Snilay@cs.wisc.edu        createNet("PipelineReg1_Out");
13810447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_output_ports; ++i)
13910447Snilay@cs.wisc.edu        {
14010447Snilay@cs.wisc.edu            createNet("PipelineReg2_In" + (String)i);
14110447Snilay@cs.wisc.edu            createNet("PipelineReg2_Out" + (String)i);
14210447Snilay@cs.wisc.edu        }
14310447Snilay@cs.wisc.edu
14410447Snilay@cs.wisc.edu        createRouterInputPort();
14510447Snilay@cs.wisc.edu        createSwitchAllocator();
14610447Snilay@cs.wisc.edu        createVirtualChannelAllocator();
14710447Snilay@cs.wisc.edu        createCrossbar();
14810447Snilay@cs.wisc.edu        createClockTree();
14910447Snilay@cs.wisc.edu        createPipelineReg();
15010447Snilay@cs.wisc.edu
15110447Snilay@cs.wisc.edu        // Get generated numbers
15210447Snilay@cs.wisc.edu        unsigned int number_crossbar_selects = getGenProperties()->get("Crossbar->NumberSelects");
15310447Snilay@cs.wisc.edu
15410447Snilay@cs.wisc.edu        // Add write buffer event
15510447Snilay@cs.wisc.edu        getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("DFFD"), "PipelineReg0", number_bits_per_flit);
15610447Snilay@cs.wisc.edu        getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("DFFQ"), "PipelineReg0", number_bits_per_flit);
15710447Snilay@cs.wisc.edu        getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("CK"), "PipelineReg0", number_bits_per_flit);
15810447Snilay@cs.wisc.edu        getEventResult("WriteBuffer")->addSubResult(getSubInstance("InputPort")->getEventResult("WriteBuffer"), "InputPort", 1.0);
15910447Snilay@cs.wisc.edu
16010447Snilay@cs.wisc.edu        // Add read buffer event
16110447Snilay@cs.wisc.edu        getEventResult("ReadBuffer")->addSubResult(getSubInstance("InputPort")->getEventResult("ReadBuffer"), "InputPort", 1.0);
16210447Snilay@cs.wisc.edu        getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("DFFD"), "PipelineReg1", number_bits_per_flit);
16310447Snilay@cs.wisc.edu        getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("DFFQ"), "PipelineReg1", number_bits_per_flit);
16410447Snilay@cs.wisc.edu        getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("CK"), "PipelineReg1", number_bits_per_flit);
16510447Snilay@cs.wisc.edu
16610447Snilay@cs.wisc.edu        // Add crossbar traversal event
16710447Snilay@cs.wisc.edu        for(unsigned int i = 1; i <= number_output_ports; ++i)
16810447Snilay@cs.wisc.edu        {
16910447Snilay@cs.wisc.edu            Result* traverse_crossbar_event = getEventResult("TraverseCrossbar->Multicast" + (String)i);
17010447Snilay@cs.wisc.edu            traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("DFFD"), "Crossbar_Sel_DFF", number_crossbar_selects);
17110447Snilay@cs.wisc.edu            traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("DFFQ"), "Crossbar_Sel_DFF", number_crossbar_selects);
17210447Snilay@cs.wisc.edu            traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("CK"), "Crossbar_Sel_DFF", number_crossbar_selects);
17310447Snilay@cs.wisc.edu            traverse_crossbar_event->addSubResult(getSubInstance("Crossbar")->getEventResult("Multicast" + (String)i), "Crossbar", 1.0);
17410447Snilay@cs.wisc.edu            for(unsigned int j = 0; j < i; ++j)
17510447Snilay@cs.wisc.edu            {
17610447Snilay@cs.wisc.edu                traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("DFFD"), "PipelineReg2_" + (String)j, number_bits_per_flit);
17710447Snilay@cs.wisc.edu                traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("DFFQ"), "PipelineReg2_" + (String)j, number_bits_per_flit);
17810447Snilay@cs.wisc.edu                traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("CK"), "PipelineReg2_" + (String)j, number_bits_per_flit);
17910447Snilay@cs.wisc.edu            }
18010447Snilay@cs.wisc.edu        }
18110447Snilay@cs.wisc.edu
18210447Snilay@cs.wisc.edu        // Add stage1 allocator arbitrate
18310447Snilay@cs.wisc.edu        Result* arb_sw_stage1_event = getEventResult("ArbitrateSwitch->ArbitrateStage1");
18410447Snilay@cs.wisc.edu        arb_sw_stage1_event->addSubResult(getSubInstance("SwitchAllocator")->getEventResult("ArbitrateStage1"), "SwitchAllocator", 1.0);
18510447Snilay@cs.wisc.edu
18610447Snilay@cs.wisc.edu        // Add stage2 allocator arbitrate
18710447Snilay@cs.wisc.edu        Result* arb_sw_stage2_event = getEventResult("ArbitrateSwitch->ArbitrateStage2");
18810447Snilay@cs.wisc.edu        arb_sw_stage2_event->addSubResult(getSubInstance("SwitchAllocator")->getEventResult("ArbitrateStage2"), "SwitchAllocator", 1.0);
18910447Snilay@cs.wisc.edu
19010447Snilay@cs.wisc.edu        // Add CK event
19110447Snilay@cs.wisc.edu        getEventResult("DistributeClock")->addSubResult(getSubInstance("ClockTree")->getEventResult("Send"), "ClockTree", 1.0);
19210447Snilay@cs.wisc.edu        return;
19310447Snilay@cs.wisc.edu    }
19410447Snilay@cs.wisc.edu
19510447Snilay@cs.wisc.edu    void Router::updateModel()
19610447Snilay@cs.wisc.edu    {
19710447Snilay@cs.wisc.edu        // Get parameters
19810447Snilay@cs.wisc.edu        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
19910447Snilay@cs.wisc.edu
20010447Snilay@cs.wisc.edu        // Update other components
20110447Snilay@cs.wisc.edu        getSubInstance("PipelineReg0")->update();
20210447Snilay@cs.wisc.edu        getSubInstance("InputPort")->update();
20310447Snilay@cs.wisc.edu        getSubInstance("PipelineReg1")->update();
20410447Snilay@cs.wisc.edu        getSubInstance("Crossbar_Sel_DFF")->update();
20510447Snilay@cs.wisc.edu        getSubInstance("Crossbar")->update();
20610447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_output_ports; ++i)
20710447Snilay@cs.wisc.edu        {
20810447Snilay@cs.wisc.edu            getSubInstance("PipelineReg2_" + (String)i)->update();
20910447Snilay@cs.wisc.edu        }
21010447Snilay@cs.wisc.edu        getSubInstance("SwitchAllocator")->update();
21110447Snilay@cs.wisc.edu
21210447Snilay@cs.wisc.edu        // Update clock tree
21310447Snilay@cs.wisc.edu        double total_clock_tree_cap = getNet("CK")->getTotalDownstreamCap();
21410447Snilay@cs.wisc.edu        double router_area = getAreaResult("Active")->calculateSum();
21510447Snilay@cs.wisc.edu        Model* clock_tree = getSubInstance("ClockTree");
21610447Snilay@cs.wisc.edu        clock_tree->setProperty("SitePitch", sqrt(router_area));
21710447Snilay@cs.wisc.edu        clock_tree->setProperty("TotalLoadCapPerBit", total_clock_tree_cap);
21810447Snilay@cs.wisc.edu        clock_tree->update();
21910447Snilay@cs.wisc.edu
22010447Snilay@cs.wisc.edu        return;
22110447Snilay@cs.wisc.edu    }
22210447Snilay@cs.wisc.edu
22310447Snilay@cs.wisc.edu    void Router::propagateTransitionInfo()
22410447Snilay@cs.wisc.edu    {
22510447Snilay@cs.wisc.edu        // Update probability
22610447Snilay@cs.wisc.edu        unsigned int number_output_ports = getParameter("NumberOutputPorts");
22710447Snilay@cs.wisc.edu
22810447Snilay@cs.wisc.edu        // Current event
22910447Snilay@cs.wisc.edu        const String& current_event = getGenProperties()->get("UseModelEvent");
23010447Snilay@cs.wisc.edu
23110447Snilay@cs.wisc.edu        ElectricalModel* pipeline_reg0 = (ElectricalModel*)getSubInstance("PipelineReg0");
23210447Snilay@cs.wisc.edu        propagatePortTransitionInfo(pipeline_reg0, "D", "FlitIn0");
23310447Snilay@cs.wisc.edu        propagatePortTransitionInfo(pipeline_reg0, "CK", "CK");
23410447Snilay@cs.wisc.edu        pipeline_reg0->use();
23510447Snilay@cs.wisc.edu
23610447Snilay@cs.wisc.edu        ElectricalModel* input_port = (ElectricalModel*)getSubInstance("InputPort");
23710447Snilay@cs.wisc.edu        propagatePortTransitionInfo(input_port, "FlitIn", pipeline_reg0, "Q");
23810447Snilay@cs.wisc.edu        propagatePortTransitionInfo(input_port, "CK", "CK");
23910447Snilay@cs.wisc.edu        input_port->getGenProperties()->set("UseModelEvent", "ReadWrite");
24010447Snilay@cs.wisc.edu        input_port->use();
24110447Snilay@cs.wisc.edu
24210447Snilay@cs.wisc.edu        ElectricalModel* pipeline_reg1 = (ElectricalModel*)getSubInstance("PipelineReg1");
24310447Snilay@cs.wisc.edu        propagatePortTransitionInfo(pipeline_reg1, "D", "FlitIn0");
24410447Snilay@cs.wisc.edu        propagatePortTransitionInfo(pipeline_reg1, "CK", "CK");
24510447Snilay@cs.wisc.edu        pipeline_reg1->use();
24610447Snilay@cs.wisc.edu
24710447Snilay@cs.wisc.edu        ElectricalModel* crossbar_sel_dff = (ElectricalModel*)getSubInstance("Crossbar_Sel_DFF");
24810447Snilay@cs.wisc.edu        assignPortTransitionInfo(crossbar_sel_dff, "D", TransitionInfo());
24910447Snilay@cs.wisc.edu        propagatePortTransitionInfo(crossbar_sel_dff, "CK", "CK");
25010447Snilay@cs.wisc.edu        crossbar_sel_dff->use();
25110447Snilay@cs.wisc.edu
25210447Snilay@cs.wisc.edu        ElectricalModel* crossbar = (ElectricalModel*)getSubInstance("Crossbar");
25310447Snilay@cs.wisc.edu        bool is_crossbar_event = false;
25410447Snilay@cs.wisc.edu        for(unsigned int i = 1; i <= number_output_ports; ++i)
25510447Snilay@cs.wisc.edu        {
25610447Snilay@cs.wisc.edu            if(current_event == ("TraverseCrossbar->Multicast" + (String)i))
25710447Snilay@cs.wisc.edu            {
25810447Snilay@cs.wisc.edu                is_crossbar_event = true;
25910447Snilay@cs.wisc.edu                // Assume the flit is sent from port 0 to port 0~i-1
26010447Snilay@cs.wisc.edu                // Apply default transition info
26110447Snilay@cs.wisc.edu                crossbar->applyTransitionInfo("Multicast" + (String)i);
26210447Snilay@cs.wisc.edu                // Overwrite transition info
26310447Snilay@cs.wisc.edu                propagatePortTransitionInfo(crossbar, "In0", "FlitIn0");
26410447Snilay@cs.wisc.edu                break;
26510447Snilay@cs.wisc.edu            }
26610447Snilay@cs.wisc.edu        }
26710447Snilay@cs.wisc.edu        if(is_crossbar_event == false)
26810447Snilay@cs.wisc.edu        {
26910447Snilay@cs.wisc.edu            crossbar->applyTransitionInfo("Multicast1");
27010447Snilay@cs.wisc.edu            propagatePortTransitionInfo(crossbar, "In0", "FlitIn0");
27110447Snilay@cs.wisc.edu        }
27210447Snilay@cs.wisc.edu        crossbar->use();
27310447Snilay@cs.wisc.edu
27410447Snilay@cs.wisc.edu        vector<ElectricalModel*> pipeline_reg2s(number_output_ports, NULL);
27510447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_output_ports; ++i)
27610447Snilay@cs.wisc.edu        {
27710447Snilay@cs.wisc.edu            pipeline_reg2s[i] = (ElectricalModel*)getSubInstance("PipelineReg2_" + (String)i);
27810447Snilay@cs.wisc.edu            propagatePortTransitionInfo(pipeline_reg2s[i], "D", "FlitIn0");
27910447Snilay@cs.wisc.edu            propagatePortTransitionInfo(pipeline_reg2s[i], "CK", "CK");
28010447Snilay@cs.wisc.edu            pipeline_reg2s[i]->use();
28110447Snilay@cs.wisc.edu        }
28210447Snilay@cs.wisc.edu
28310447Snilay@cs.wisc.edu        ElectricalModel* sw_allocator = (ElectricalModel*)getSubInstance("SwitchAllocator");
28410447Snilay@cs.wisc.edu        if(current_event == "ArbitrateSwitch->ArbitrateStage1")
28510447Snilay@cs.wisc.edu        {
28610447Snilay@cs.wisc.edu            sw_allocator->applyTransitionInfo("ArbitrateStage1");
28710447Snilay@cs.wisc.edu        }
28810447Snilay@cs.wisc.edu        else if(current_event == "ArbitrateSwitch->ArbitrateStage2")
28910447Snilay@cs.wisc.edu        {
29010447Snilay@cs.wisc.edu            sw_allocator->applyTransitionInfo("ArbitrateStage2");
29110447Snilay@cs.wisc.edu        }
29210447Snilay@cs.wisc.edu        else
29310447Snilay@cs.wisc.edu        {
29410447Snilay@cs.wisc.edu            sw_allocator->applyTransitionInfo("Idle");
29510447Snilay@cs.wisc.edu        }
29610447Snilay@cs.wisc.edu        sw_allocator->use();
29710447Snilay@cs.wisc.edu
29810447Snilay@cs.wisc.edu        ElectricalModel* clock_tree = (ElectricalModel*)getSubInstance("ClockTree");
29910447Snilay@cs.wisc.edu        propagatePortTransitionInfo(clock_tree, "In", "CK");
30010447Snilay@cs.wisc.edu        clock_tree->use();
30110447Snilay@cs.wisc.edu        return;
30210447Snilay@cs.wisc.edu    }
30310447Snilay@cs.wisc.edu
30410447Snilay@cs.wisc.edu    void Router::createRouterInputPort()
30510447Snilay@cs.wisc.edu    {
30610447Snilay@cs.wisc.edu        // Get parameters
30710447Snilay@cs.wisc.edu        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
30810447Snilay@cs.wisc.edu        unsigned int number_vns = getParameter("NumberVirtualNetworks").toUInt();
30910447Snilay@cs.wisc.edu        const String& number_vcs_per_vn = getParameter("NumberVirtualChannelsPerVirtualNetwork");
31010447Snilay@cs.wisc.edu        const String& number_bufs_per_vc = getParameter("NumberBuffersPerVirtualChannel");
31110447Snilay@cs.wisc.edu        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
31210447Snilay@cs.wisc.edu        const String& buffer_model = getParameter("InputPort->BufferModel");
31310447Snilay@cs.wisc.edu
31410447Snilay@cs.wisc.edu        // Init input port model
31510447Snilay@cs.wisc.edu        const String& input_port_name = "InputPort";
31610447Snilay@cs.wisc.edu        RouterInputPort* input_port = new RouterInputPort(input_port_name, getTechModel());
31710447Snilay@cs.wisc.edu        input_port->setParameter("NumberVirtualNetworks", number_vns);
31810447Snilay@cs.wisc.edu        input_port->setParameter("NumberVirtualChannelsPerVirtualNetwork", number_vcs_per_vn);
31910447Snilay@cs.wisc.edu        input_port->setParameter("NumberBuffersPerVirtualChannel", number_bufs_per_vc);
32010447Snilay@cs.wisc.edu        input_port->setParameter("NumberBitsPerFlit", number_bits_per_flit);
32110447Snilay@cs.wisc.edu        input_port->setParameter("BufferModel", buffer_model);
32210447Snilay@cs.wisc.edu        input_port->construct();
32310447Snilay@cs.wisc.edu
32410447Snilay@cs.wisc.edu        unsigned int number_input_port_outputs = input_port->getGenProperties()->get("NumberOutputs");
32510447Snilay@cs.wisc.edu        unsigned int number_input_port_addr_bits = input_port->getGenProperties()->get("NumberAddressBits");
32610447Snilay@cs.wisc.edu        getGenProperties()->set("InputPort->NumberOutputs", number_input_port_outputs);
32710447Snilay@cs.wisc.edu        getGenProperties()->set("InputPort->NumberAddressBits", number_input_port_addr_bits);
32810447Snilay@cs.wisc.edu
32910447Snilay@cs.wisc.edu        unsigned int total_number_vcs = input_port->getGenProperties()->get("TotalNumberVirtualChannels");
33010447Snilay@cs.wisc.edu        getGenProperties()->set("TotalNumberVirtualChannels", total_number_vcs);
33110447Snilay@cs.wisc.edu
33210447Snilay@cs.wisc.edu        // Add the instance and the results
33310447Snilay@cs.wisc.edu        addSubInstances(input_port, number_input_ports);
33410447Snilay@cs.wisc.edu        addElectricalSubResults(input_port, number_input_ports);
33510447Snilay@cs.wisc.edu
33610447Snilay@cs.wisc.edu        // Create connections
33710447Snilay@cs.wisc.edu        createNet("InputPort_In", makeNetIndex(0, number_bits_per_flit-1));
33810447Snilay@cs.wisc.edu        createNet("InputPort_Out", makeNetIndex(0, number_bits_per_flit-1));
33910447Snilay@cs.wisc.edu
34010447Snilay@cs.wisc.edu        assignVirtualFanout("InputPort_In", "PipelineReg0_Out");
34110447Snilay@cs.wisc.edu        portConnect(input_port, "FlitIn", "InputPort_In");
34210447Snilay@cs.wisc.edu        portConnect(input_port, "CK", "CK");
34310447Snilay@cs.wisc.edu        portConnect(input_port, "FlitOut", "InputPort_Out");
34410447Snilay@cs.wisc.edu        assignVirtualFanin("PipelineReg1_In", "InputPort_Out");
34510447Snilay@cs.wisc.edu
34610447Snilay@cs.wisc.edu        return;
34710447Snilay@cs.wisc.edu    }
34810447Snilay@cs.wisc.edu
34910447Snilay@cs.wisc.edu    void Router::createVirtualChannelAllocator()
35010447Snilay@cs.wisc.edu    {}
35110447Snilay@cs.wisc.edu
35210447Snilay@cs.wisc.edu    void Router::createSwitchAllocator()
35310447Snilay@cs.wisc.edu    {
35410447Snilay@cs.wisc.edu        // Get parameters
35510447Snilay@cs.wisc.edu        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
35610447Snilay@cs.wisc.edu        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
35710447Snilay@cs.wisc.edu        unsigned int total_number_vcs = getGenProperties()->get("TotalNumberVirtualChannels").toUInt();
35810447Snilay@cs.wisc.edu        const String& arb_model = getParameter("SwitchAllocator->ArbiterModel");
35910447Snilay@cs.wisc.edu
36010447Snilay@cs.wisc.edu        // Init switch allocator model
36110447Snilay@cs.wisc.edu        const String& sw_allocator_name = "SwitchAllocator";
36210447Snilay@cs.wisc.edu        RouterSwitchAllocator* sw_allocator = new RouterSwitchAllocator(sw_allocator_name, getTechModel());
36310447Snilay@cs.wisc.edu        sw_allocator->setParameter("NumberInputPorts", number_input_ports);
36410447Snilay@cs.wisc.edu        sw_allocator->setParameter("NumberOutputPorts", number_output_ports);
36510447Snilay@cs.wisc.edu        sw_allocator->setParameter("TotalNumberVirtualChannels", total_number_vcs);
36610447Snilay@cs.wisc.edu        sw_allocator->setParameter("ArbiterModel", arb_model);
36710447Snilay@cs.wisc.edu        sw_allocator->construct();
36810447Snilay@cs.wisc.edu
36910447Snilay@cs.wisc.edu        // Add the instance and the results
37010447Snilay@cs.wisc.edu        addSubInstances(sw_allocator, 1.0);
37110447Snilay@cs.wisc.edu        addElectricalSubResults(sw_allocator, 1.0);
37210447Snilay@cs.wisc.edu
37310447Snilay@cs.wisc.edu        // Create connections (currently connect CK only)
37410447Snilay@cs.wisc.edu        portConnect(sw_allocator, "CK", "CK");
37510447Snilay@cs.wisc.edu        return;
37610447Snilay@cs.wisc.edu    }
37710447Snilay@cs.wisc.edu
37810447Snilay@cs.wisc.edu    void Router::createCrossbar()
37910447Snilay@cs.wisc.edu    {
38010447Snilay@cs.wisc.edu        // Get parameters
38110447Snilay@cs.wisc.edu        const String& crossbar_model = getParameter("CrossbarModel");
38210447Snilay@cs.wisc.edu        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
38310447Snilay@cs.wisc.edu        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
38410447Snilay@cs.wisc.edu        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
38510447Snilay@cs.wisc.edu        unsigned int number_input_port_outputs = getGenProperties()->get("InputPort->NumberOutputs").toUInt();
38610447Snilay@cs.wisc.edu
38710447Snilay@cs.wisc.edu        unsigned int number_crossbar_inputs = number_input_port_outputs * number_input_ports;
38810447Snilay@cs.wisc.edu        unsigned int number_crossbar_outputs = number_output_ports;
38910447Snilay@cs.wisc.edu        getGenProperties()->set("Crossbar->NumberInputs", number_crossbar_inputs);
39010447Snilay@cs.wisc.edu        getGenProperties()->set("Crossbar->NumberOutputs", number_crossbar_outputs);
39110447Snilay@cs.wisc.edu
39210447Snilay@cs.wisc.edu        // Init crossbar model
39310447Snilay@cs.wisc.edu        const String& crossbar_name = "Crossbar";
39410447Snilay@cs.wisc.edu        ElectricalModel* crossbar = ModelGen::createCrossbar(crossbar_model, crossbar_name, getTechModel());
39510447Snilay@cs.wisc.edu        crossbar->setParameter("NumberInputs", number_crossbar_inputs);
39610447Snilay@cs.wisc.edu        crossbar->setParameter("NumberOutputs", number_crossbar_outputs);
39710447Snilay@cs.wisc.edu        crossbar->setParameter("NumberBits", number_bits_per_flit);
39810447Snilay@cs.wisc.edu        crossbar->setParameter("BitDuplicate", "TRUE");
39910447Snilay@cs.wisc.edu        crossbar->construct();
40010447Snilay@cs.wisc.edu
40110447Snilay@cs.wisc.edu        unsigned int number_crossbar_selects = crossbar->getGenProperties()->get("NumberSelectsPerPort");
40210447Snilay@cs.wisc.edu        getGenProperties()->set("Crossbar->NumberSelects", number_crossbar_selects);
40310447Snilay@cs.wisc.edu
40410447Snilay@cs.wisc.edu        // Init DFF for crossbar selections
40510447Snilay@cs.wisc.edu        const String& crossbar_sel_dff_name = "Crossbar_Sel_DFF";
40610447Snilay@cs.wisc.edu        StdCell* crossbar_sel_dff = getTechModel()->getStdCellLib()->createStdCell("DFFQ", crossbar_sel_dff_name);
40710447Snilay@cs.wisc.edu        crossbar_sel_dff->construct();
40810447Snilay@cs.wisc.edu
40910447Snilay@cs.wisc.edu        // Add instances and results
41010447Snilay@cs.wisc.edu        addSubInstances(crossbar, 1.0);
41110447Snilay@cs.wisc.edu        addElectricalSubResults(crossbar, 1.0);
41210447Snilay@cs.wisc.edu
41310447Snilay@cs.wisc.edu        addSubInstances(crossbar_sel_dff, number_crossbar_outputs * number_crossbar_selects);
41410447Snilay@cs.wisc.edu        addElectricalSubResults(crossbar_sel_dff, number_crossbar_outputs * number_crossbar_selects);
41510447Snilay@cs.wisc.edu
41610447Snilay@cs.wisc.edu        // Create connections
41710447Snilay@cs.wisc.edu        createNet("Crossbar_Sel_DFF_Out");
41810447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_crossbar_outputs; ++i)
41910447Snilay@cs.wisc.edu        {
42010447Snilay@cs.wisc.edu            for(unsigned int j = 0; j < number_crossbar_selects; ++j)
42110447Snilay@cs.wisc.edu            {
42210447Snilay@cs.wisc.edu                createNet(String::format("Crossbar_Sel%d_%d", i, j));
42310447Snilay@cs.wisc.edu            }
42410447Snilay@cs.wisc.edu            createNet("Crossbar_Out" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
42510447Snilay@cs.wisc.edu        }
42610447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
42710447Snilay@cs.wisc.edu        {
42810447Snilay@cs.wisc.edu            createNet("Crossbar_In" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
42910447Snilay@cs.wisc.edu        }
43010447Snilay@cs.wisc.edu
43110447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_crossbar_selects; ++i)
43210447Snilay@cs.wisc.edu        {
43310447Snilay@cs.wisc.edu            portConnect(crossbar_sel_dff, "CK", "CK");
43410447Snilay@cs.wisc.edu        }
43510447Snilay@cs.wisc.edu        portConnect(crossbar_sel_dff, "Q", "Crossbar_Sel_DFF_Out");
43610447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
43710447Snilay@cs.wisc.edu        {
43810447Snilay@cs.wisc.edu            assignVirtualFanout("Crossbar_In" + (String)i, "PipelineReg1_Out");
43910447Snilay@cs.wisc.edu            portConnect(crossbar, "In" + (String)i, "Crossbar_In" + (String)i);
44010447Snilay@cs.wisc.edu        }
44110447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_crossbar_outputs; ++i)
44210447Snilay@cs.wisc.edu        {
44310447Snilay@cs.wisc.edu            for(unsigned int j = 0; j < number_crossbar_selects; ++j)
44410447Snilay@cs.wisc.edu            {
44510447Snilay@cs.wisc.edu                assignVirtualFanout(String::format("Crossbar_Sel%d_%d", i, j), "Crossbar_Sel_DFF_Out");
44610447Snilay@cs.wisc.edu                portConnect(crossbar, String::format("Sel%d_%d", i, j), String::format("Crossbar_Sel%d_%d", i, j));
44710447Snilay@cs.wisc.edu            }
44810447Snilay@cs.wisc.edu            portConnect(crossbar, "Out" + (String)i, "Crossbar_Out" + (String)i);
44910447Snilay@cs.wisc.edu            assignVirtualFanin("PipelineReg2_In" + (String)i, "Crossbar_Out" + (String)i);
45010447Snilay@cs.wisc.edu        }
45110447Snilay@cs.wisc.edu
45210447Snilay@cs.wisc.edu        return;
45310447Snilay@cs.wisc.edu    }
45410447Snilay@cs.wisc.edu
45510447Snilay@cs.wisc.edu    void Router::createPipelineReg()
45610447Snilay@cs.wisc.edu    {
45710447Snilay@cs.wisc.edu        // Get parameters
45810447Snilay@cs.wisc.edu        unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
45910447Snilay@cs.wisc.edu        unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
46010447Snilay@cs.wisc.edu        unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
46110447Snilay@cs.wisc.edu        unsigned int number_crossbar_inputs = getGenProperties()->get("Crossbar->NumberInputs");
46210447Snilay@cs.wisc.edu
46310447Snilay@cs.wisc.edu        // Init pipeline reg model
46410447Snilay@cs.wisc.edu        // First stage: from router input to input port
46510447Snilay@cs.wisc.edu        const String& pipeline_reg0_name = "PipelineReg0";
46610447Snilay@cs.wisc.edu        StdCell* pipeline_reg0 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg0_name);
46710447Snilay@cs.wisc.edu        pipeline_reg0->construct();
46810447Snilay@cs.wisc.edu        // Second stage: from input port to crossbar
46910447Snilay@cs.wisc.edu        const String& pipeline_reg1_name = "PipelineReg1";
47010447Snilay@cs.wisc.edu        StdCell* pipeline_reg1 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg1_name);
47110447Snilay@cs.wisc.edu        pipeline_reg1->construct();
47210447Snilay@cs.wisc.edu
47310447Snilay@cs.wisc.edu        // Third stage: from crossbar to router output
47410447Snilay@cs.wisc.edu        vector<StdCell*> pipeline_reg2s(number_output_ports, (StdCell*)NULL);
47510447Snilay@cs.wisc.edu        vector<String> pipeline_reg2_names(number_output_ports, "");
47610447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_output_ports; ++i)
47710447Snilay@cs.wisc.edu        {
47810447Snilay@cs.wisc.edu            pipeline_reg2_names[i] = "PipelineReg2_" + (String)i;
47910447Snilay@cs.wisc.edu            pipeline_reg2s[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg2_names[i]);
48010447Snilay@cs.wisc.edu            pipeline_reg2s[i]->construct();
48110447Snilay@cs.wisc.edu        }
48210447Snilay@cs.wisc.edu
48310447Snilay@cs.wisc.edu        // Add instances and results
48410447Snilay@cs.wisc.edu        addSubInstances(pipeline_reg0, number_input_ports * number_bits_per_flit);
48510447Snilay@cs.wisc.edu        addElectricalSubResults(pipeline_reg0, number_input_ports * number_bits_per_flit);
48610447Snilay@cs.wisc.edu
48710447Snilay@cs.wisc.edu        addSubInstances(pipeline_reg1, number_crossbar_inputs * number_bits_per_flit);
48810447Snilay@cs.wisc.edu        addElectricalSubResults(pipeline_reg1, number_crossbar_inputs * number_bits_per_flit);
48910447Snilay@cs.wisc.edu
49010447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_output_ports; ++i)
49110447Snilay@cs.wisc.edu        {
49210447Snilay@cs.wisc.edu            addSubInstances(pipeline_reg2s[i], number_bits_per_flit);
49310447Snilay@cs.wisc.edu            addElectricalSubResults(pipeline_reg2s[i], number_bits_per_flit);
49410447Snilay@cs.wisc.edu        }
49510447Snilay@cs.wisc.edu
49610447Snilay@cs.wisc.edu        // Create data connections
49710447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_input_ports; ++i)
49810447Snilay@cs.wisc.edu        {
49910447Snilay@cs.wisc.edu            assignVirtualFanin("PipelineReg0_In", "FlitIn" + (String)i);
50010447Snilay@cs.wisc.edu        }
50110447Snilay@cs.wisc.edu        portConnect(pipeline_reg0, "D", "PipelineReg0_In");
50210447Snilay@cs.wisc.edu        portConnect(pipeline_reg0, "Q", "PipelineReg0_Out");
50310447Snilay@cs.wisc.edu        portConnect(pipeline_reg1, "D", "PipelineReg1_In");
50410447Snilay@cs.wisc.edu        portConnect(pipeline_reg1, "Q", "PipelineReg1_Out");
50510447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < number_output_ports; ++i)
50610447Snilay@cs.wisc.edu        {
50710447Snilay@cs.wisc.edu            portConnect(pipeline_reg2s[i], "D", "PipelineReg2_In" + (String)i);
50810447Snilay@cs.wisc.edu            portConnect(pipeline_reg2s[i], "Q", "PipelineReg2_Out" + (String)i);
50910447Snilay@cs.wisc.edu            assignVirtualFanout("FlitOut" + (String)i, "PipelineReg2_Out" + (String)i);
51010447Snilay@cs.wisc.edu        }
51110447Snilay@cs.wisc.edu
51210447Snilay@cs.wisc.edu        // Create CK connections
51310447Snilay@cs.wisc.edu        for(unsigned int n = 0; n < number_bits_per_flit; ++n)
51410447Snilay@cs.wisc.edu        {
51510447Snilay@cs.wisc.edu            for(unsigned int i = 0; i < number_input_ports; ++i)
51610447Snilay@cs.wisc.edu            {
51710447Snilay@cs.wisc.edu                portConnect(pipeline_reg0, "CK", "CK");
51810447Snilay@cs.wisc.edu            }
51910447Snilay@cs.wisc.edu            for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
52010447Snilay@cs.wisc.edu            {
52110447Snilay@cs.wisc.edu                portConnect(pipeline_reg1, "CK", "CK");
52210447Snilay@cs.wisc.edu            }
52310447Snilay@cs.wisc.edu            for(unsigned int i = 0; i < number_output_ports; ++i)
52410447Snilay@cs.wisc.edu            {
52510447Snilay@cs.wisc.edu                portConnect(pipeline_reg2s[i], "CK", "CK");
52610447Snilay@cs.wisc.edu            }
52710447Snilay@cs.wisc.edu        }
52810447Snilay@cs.wisc.edu        return;
52910447Snilay@cs.wisc.edu    }
53010447Snilay@cs.wisc.edu
53110447Snilay@cs.wisc.edu    void Router::createClockTree()
53210447Snilay@cs.wisc.edu    {
53310447Snilay@cs.wisc.edu        // Get parameters
53410447Snilay@cs.wisc.edu        const String& clock_tree_model = getParameter("ClockTreeModel");
53510447Snilay@cs.wisc.edu        const String& clock_tree_number_levels = getParameter("ClockTree->NumberLevels");
53610447Snilay@cs.wisc.edu        const String& clock_tree_wire_layer = getParameter("ClockTree->WireLayer");
53710447Snilay@cs.wisc.edu        const String& clock_tree_wire_width_multiplier = getParameter("ClockTree->WireWidthMultiplier");
53810447Snilay@cs.wisc.edu        const String& clock_tree_wire_spacing_multiplier = getParameter("ClockTree->WireSpacingMultiplier");
53910447Snilay@cs.wisc.edu
54010447Snilay@cs.wisc.edu        // Init clock tree model
54110447Snilay@cs.wisc.edu        const String& clock_tree_name = "ClockTree";
54210447Snilay@cs.wisc.edu        ElectricalModel* clock_tree = (ElectricalModel*)ModelGen::createModel(clock_tree_model, clock_tree_name, getTechModel());
54310447Snilay@cs.wisc.edu        clock_tree->setParameter("NumberLevels", clock_tree_number_levels);
54410447Snilay@cs.wisc.edu        clock_tree->setParameter("NumberBits", 1);
54510447Snilay@cs.wisc.edu        clock_tree->setParameter("WireLayer", clock_tree_wire_layer);
54610447Snilay@cs.wisc.edu        clock_tree->setParameter("WireWidthMultiplier", clock_tree_wire_width_multiplier);
54710447Snilay@cs.wisc.edu        clock_tree->setParameter("WireSpacingMultiplier", clock_tree_wire_spacing_multiplier);
54810447Snilay@cs.wisc.edu        clock_tree->construct();
54910447Snilay@cs.wisc.edu
55010447Snilay@cs.wisc.edu        // Add instances and results
55110447Snilay@cs.wisc.edu        addSubInstances(clock_tree, 1.0);
55210447Snilay@cs.wisc.edu        addElectricalSubResults(clock_tree, 1.0);
55310447Snilay@cs.wisc.edu
55410447Snilay@cs.wisc.edu        return;
55510447Snilay@cs.wisc.edu    }
55610447Snilay@cs.wisc.edu} // namespace DSENT
55710447Snilay@cs.wisc.edu
558