summaryrefslogtreecommitdiff
path: root/ext/dsent/model/electrical/router
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dsent/model/electrical/router')
-rw-r--r--ext/dsent/model/electrical/router/Router.cc536
-rw-r--r--ext/dsent/model/electrical/router/Router.h46
-rw-r--r--ext/dsent/model/electrical/router/RouterInputPort.cc201
-rw-r--r--ext/dsent/model/electrical/router/RouterInputPort.h33
-rw-r--r--ext/dsent/model/electrical/router/RouterSwitchAllocator.cc199
-rw-r--r--ext/dsent/model/electrical/router/RouterSwitchAllocator.h33
6 files changed, 1048 insertions, 0 deletions
diff --git a/ext/dsent/model/electrical/router/Router.cc b/ext/dsent/model/electrical/router/Router.cc
new file mode 100644
index 000000000..c079bd1d5
--- /dev/null
+++ b/ext/dsent/model/electrical/router/Router.cc
@@ -0,0 +1,536 @@
+#include "model/electrical/router/Router.h"
+
+#include <cmath>
+#include <vector>
+
+#include "model/PortInfo.h"
+#include "model/EventInfo.h"
+#include "model/TransitionInfo.h"
+#include "model/ModelGen.h"
+#include "model/std_cells/StdCellLib.h"
+#include "model/std_cells/StdCell.h"
+#include "model/electrical/router/RouterInputPort.h"
+#include "model/electrical/router/RouterSwitchAllocator.h"
+#include "model/timing_graph/ElectricalNet.h"
+
+namespace DSENT
+{
+ using std::sqrt;
+ using std::vector;
+
+ using LibUtil::castStringVector;
+ using LibUtil::vectorToString;
+
+ Router::Router(const String& instance_name_, const TechModel* tech_model_)
+ : ElectricalModel(instance_name_, tech_model_)
+ {
+ initParameters();
+ initProperties();
+ }
+
+ Router::~Router()
+ {}
+
+ void Router::initParameters()
+ {
+ addParameterName("NumberInputPorts");
+ addParameterName("NumberOutputPorts");
+ addParameterName("NumberBitsPerFlit");
+ addParameterName("NumberVirtualNetworks");
+ addParameterName("NumberVirtualChannelsPerVirtualNetwork");
+ addParameterName("NumberBuffersPerVirtualChannel");
+ // Spec for input port
+ addParameterName("InputPort->BufferModel");
+ // Spec for crossbar
+ addParameterName("CrossbarModel");
+ // Spec for switch allocator
+ addParameterName("SwitchAllocator->ArbiterModel");
+ // Spec for clock tree
+ addParameterName("ClockTreeModel");
+ addParameterName("ClockTree->NumberLevels");
+ addParameterName("ClockTree->WireLayer");
+ addParameterName("ClockTree->WireWidthMultiplier");
+ addParameterName("ClockTree->WireSpacingMultiplier", 3.0);
+ return;
+ }
+
+ void Router::initProperties()
+ {
+ return;
+ }
+
+ Router* Router::clone() const
+ {
+ // TODO
+ return NULL;
+ }
+
+ void Router::constructModel()
+ {
+ // Get parameters
+ unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
+ unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
+ unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
+
+ ASSERT(number_input_ports > 0, "[Error] " + getInstanceName() +
+ " -> Number of input ports must be > 0!");
+ ASSERT(number_output_ports > 0, "[Error] " + getInstanceName() +
+ " -> Number of output ports must be > 0!");
+ ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() +
+ " -> Number of bits per buffer must be > 0!");
+
+ // Create ports
+ createInputPort("CK");
+ for(unsigned int i = 0; i < number_input_ports; ++i)
+ {
+ createInputPort("FlitIn" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
+ }
+ for(unsigned int i = 0; i < number_output_ports; ++i)
+ {
+ createOutputPort("FlitOut" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
+ }
+
+ // Create area, power, event results
+ createElectricalResults();
+ getEventInfo("Idle")->setStaticTransitionInfos();
+ getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+
+ createElectricalEventResult("ReadBuffer");
+ getEventInfo("ReadBuffer")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+ createElectricalEventResult("WriteBuffer");
+ getEventInfo("WriteBuffer")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+ for(unsigned int i = 1; i <= number_output_ports; ++i)
+ {
+ createElectricalEventResult("TraverseCrossbar->Multicast" + (String)i);
+ getEventInfo("TraverseCrossbar->Multicast" + (String)i)->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+ }
+ createElectricalEventResult("ArbitrateSwitch->ArbitrateStage1");
+ createElectricalEventResult("ArbitrateSwitch->ArbitrateStage2");
+ createElectricalEventResult("DistributeClock");
+ getEventInfo("DistributeClock")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+
+ // Create intermediate nets
+ createNet("PipelineReg0_In");
+ createNet("PipelineReg0_Out");
+ createNet("PipelineReg1_In");
+ createNet("PipelineReg1_Out");
+ for(unsigned int i = 0; i < number_output_ports; ++i)
+ {
+ createNet("PipelineReg2_In" + (String)i);
+ createNet("PipelineReg2_Out" + (String)i);
+ }
+
+ createRouterInputPort();
+ createSwitchAllocator();
+ createVirtualChannelAllocator();
+ createCrossbar();
+ createClockTree();
+ createPipelineReg();
+
+ // Get generated numbers
+ unsigned int number_crossbar_selects = getGenProperties()->get("Crossbar->NumberSelects");
+
+ // Add write buffer event
+ getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("DFFD"), "PipelineReg0", number_bits_per_flit);
+ getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("DFFQ"), "PipelineReg0", number_bits_per_flit);
+ getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("CK"), "PipelineReg0", number_bits_per_flit);
+ getEventResult("WriteBuffer")->addSubResult(getSubInstance("InputPort")->getEventResult("WriteBuffer"), "InputPort", 1.0);
+
+ // Add read buffer event
+ getEventResult("ReadBuffer")->addSubResult(getSubInstance("InputPort")->getEventResult("ReadBuffer"), "InputPort", 1.0);
+ getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("DFFD"), "PipelineReg1", number_bits_per_flit);
+ getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("DFFQ"), "PipelineReg1", number_bits_per_flit);
+ getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("CK"), "PipelineReg1", number_bits_per_flit);
+
+ // Add crossbar traversal event
+ for(unsigned int i = 1; i <= number_output_ports; ++i)
+ {
+ Result* traverse_crossbar_event = getEventResult("TraverseCrossbar->Multicast" + (String)i);
+ traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("DFFD"), "Crossbar_Sel_DFF", number_crossbar_selects);
+ traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("DFFQ"), "Crossbar_Sel_DFF", number_crossbar_selects);
+ traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("CK"), "Crossbar_Sel_DFF", number_crossbar_selects);
+ traverse_crossbar_event->addSubResult(getSubInstance("Crossbar")->getEventResult("Multicast" + (String)i), "Crossbar", 1.0);
+ for(unsigned int j = 0; j < i; ++j)
+ {
+ traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("DFFD"), "PipelineReg2_" + (String)j, number_bits_per_flit);
+ traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("DFFQ"), "PipelineReg2_" + (String)j, number_bits_per_flit);
+ traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("CK"), "PipelineReg2_" + (String)j, number_bits_per_flit);
+ }
+ }
+
+ // Add stage1 allocator arbitrate
+ Result* arb_sw_stage1_event = getEventResult("ArbitrateSwitch->ArbitrateStage1");
+ arb_sw_stage1_event->addSubResult(getSubInstance("SwitchAllocator")->getEventResult("ArbitrateStage1"), "SwitchAllocator", 1.0);
+
+ // Add stage2 allocator arbitrate
+ Result* arb_sw_stage2_event = getEventResult("ArbitrateSwitch->ArbitrateStage2");
+ arb_sw_stage2_event->addSubResult(getSubInstance("SwitchAllocator")->getEventResult("ArbitrateStage2"), "SwitchAllocator", 1.0);
+
+ // Add CK event
+ getEventResult("DistributeClock")->addSubResult(getSubInstance("ClockTree")->getEventResult("Send"), "ClockTree", 1.0);
+ return;
+ }
+
+ void Router::updateModel()
+ {
+ // Get parameters
+ unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
+
+ // Update other components
+ getSubInstance("PipelineReg0")->update();
+ getSubInstance("InputPort")->update();
+ getSubInstance("PipelineReg1")->update();
+ getSubInstance("Crossbar_Sel_DFF")->update();
+ getSubInstance("Crossbar")->update();
+ for(unsigned int i = 0; i < number_output_ports; ++i)
+ {
+ getSubInstance("PipelineReg2_" + (String)i)->update();
+ }
+ getSubInstance("SwitchAllocator")->update();
+
+ // Update clock tree
+ double total_clock_tree_cap = getNet("CK")->getTotalDownstreamCap();
+ double router_area = getAreaResult("Active")->calculateSum();
+ Model* clock_tree = getSubInstance("ClockTree");
+ clock_tree->setProperty("SitePitch", sqrt(router_area));
+ clock_tree->setProperty("TotalLoadCapPerBit", total_clock_tree_cap);
+ clock_tree->update();
+
+ return;
+ }
+
+ void Router::propagateTransitionInfo()
+ {
+ // Update probability
+ unsigned int number_output_ports = getParameter("NumberOutputPorts");
+
+ // Current event
+ const String& current_event = getGenProperties()->get("UseModelEvent");
+
+ ElectricalModel* pipeline_reg0 = (ElectricalModel*)getSubInstance("PipelineReg0");
+ propagatePortTransitionInfo(pipeline_reg0, "D", "FlitIn0");
+ propagatePortTransitionInfo(pipeline_reg0, "CK", "CK");
+ pipeline_reg0->use();
+
+ ElectricalModel* input_port = (ElectricalModel*)getSubInstance("InputPort");
+ propagatePortTransitionInfo(input_port, "FlitIn", pipeline_reg0, "Q");
+ propagatePortTransitionInfo(input_port, "CK", "CK");
+ input_port->getGenProperties()->set("UseModelEvent", "ReadWrite");
+ input_port->use();
+
+ ElectricalModel* pipeline_reg1 = (ElectricalModel*)getSubInstance("PipelineReg1");
+ propagatePortTransitionInfo(pipeline_reg1, "D", "FlitIn0");
+ propagatePortTransitionInfo(pipeline_reg1, "CK", "CK");
+ pipeline_reg1->use();
+
+ ElectricalModel* crossbar_sel_dff = (ElectricalModel*)getSubInstance("Crossbar_Sel_DFF");
+ assignPortTransitionInfo(crossbar_sel_dff, "D", TransitionInfo());
+ propagatePortTransitionInfo(crossbar_sel_dff, "CK", "CK");
+ crossbar_sel_dff->use();
+
+ ElectricalModel* crossbar = (ElectricalModel*)getSubInstance("Crossbar");
+ bool is_crossbar_event = false;
+ for(unsigned int i = 1; i <= number_output_ports; ++i)
+ {
+ if(current_event == ("TraverseCrossbar->Multicast" + (String)i))
+ {
+ is_crossbar_event = true;
+ // Assume the flit is sent from port 0 to port 0~i-1
+ // Apply default transition info
+ crossbar->applyTransitionInfo("Multicast" + (String)i);
+ // Overwrite transition info
+ propagatePortTransitionInfo(crossbar, "In0", "FlitIn0");
+ break;
+ }
+ }
+ if(is_crossbar_event == false)
+ {
+ crossbar->applyTransitionInfo("Multicast1");
+ propagatePortTransitionInfo(crossbar, "In0", "FlitIn0");
+ }
+ crossbar->use();
+
+ vector<ElectricalModel*> pipeline_reg2s(number_output_ports, NULL);
+ for(unsigned int i = 0; i < number_output_ports; ++i)
+ {
+ pipeline_reg2s[i] = (ElectricalModel*)getSubInstance("PipelineReg2_" + (String)i);
+ propagatePortTransitionInfo(pipeline_reg2s[i], "D", "FlitIn0");
+ propagatePortTransitionInfo(pipeline_reg2s[i], "CK", "CK");
+ pipeline_reg2s[i]->use();
+ }
+
+ ElectricalModel* sw_allocator = (ElectricalModel*)getSubInstance("SwitchAllocator");
+ if(current_event == "ArbitrateSwitch->ArbitrateStage1")
+ {
+ sw_allocator->applyTransitionInfo("ArbitrateStage1");
+ }
+ else if(current_event == "ArbitrateSwitch->ArbitrateStage2")
+ {
+ sw_allocator->applyTransitionInfo("ArbitrateStage2");
+ }
+ else
+ {
+ sw_allocator->applyTransitionInfo("Idle");
+ }
+ sw_allocator->use();
+
+ ElectricalModel* clock_tree = (ElectricalModel*)getSubInstance("ClockTree");
+ propagatePortTransitionInfo(clock_tree, "In", "CK");
+ clock_tree->use();
+ return;
+ }
+
+ void Router::createRouterInputPort()
+ {
+ // Get parameters
+ unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
+ unsigned int number_vns = getParameter("NumberVirtualNetworks").toUInt();
+ const String& number_vcs_per_vn = getParameter("NumberVirtualChannelsPerVirtualNetwork");
+ const String& number_bufs_per_vc = getParameter("NumberBuffersPerVirtualChannel");
+ unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
+ const String& buffer_model = getParameter("InputPort->BufferModel");
+
+ // Init input port model
+ const String& input_port_name = "InputPort";
+ RouterInputPort* input_port = new RouterInputPort(input_port_name, getTechModel());
+ input_port->setParameter("NumberVirtualNetworks", number_vns);
+ input_port->setParameter("NumberVirtualChannelsPerVirtualNetwork", number_vcs_per_vn);
+ input_port->setParameter("NumberBuffersPerVirtualChannel", number_bufs_per_vc);
+ input_port->setParameter("NumberBitsPerFlit", number_bits_per_flit);
+ input_port->setParameter("BufferModel", buffer_model);
+ input_port->construct();
+
+ unsigned int number_input_port_outputs = input_port->getGenProperties()->get("NumberOutputs");
+ unsigned int number_input_port_addr_bits = input_port->getGenProperties()->get("NumberAddressBits");
+ getGenProperties()->set("InputPort->NumberOutputs", number_input_port_outputs);
+ getGenProperties()->set("InputPort->NumberAddressBits", number_input_port_addr_bits);
+
+ unsigned int total_number_vcs = input_port->getGenProperties()->get("TotalNumberVirtualChannels");
+ getGenProperties()->set("TotalNumberVirtualChannels", total_number_vcs);
+
+ // Add the instance and the results
+ addSubInstances(input_port, number_input_ports);
+ addElectricalSubResults(input_port, number_input_ports);
+
+ // Create connections
+ createNet("InputPort_In", makeNetIndex(0, number_bits_per_flit-1));
+ createNet("InputPort_Out", makeNetIndex(0, number_bits_per_flit-1));
+
+ assignVirtualFanout("InputPort_In", "PipelineReg0_Out");
+ portConnect(input_port, "FlitIn", "InputPort_In");
+ portConnect(input_port, "CK", "CK");
+ portConnect(input_port, "FlitOut", "InputPort_Out");
+ assignVirtualFanin("PipelineReg1_In", "InputPort_Out");
+
+ return;
+ }
+
+ void Router::createVirtualChannelAllocator()
+ {}
+
+ void Router::createSwitchAllocator()
+ {
+ // Get parameters
+ unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
+ unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
+ unsigned int total_number_vcs = getGenProperties()->get("TotalNumberVirtualChannels").toUInt();
+ const String& arb_model = getParameter("SwitchAllocator->ArbiterModel");
+
+ // Init switch allocator model
+ const String& sw_allocator_name = "SwitchAllocator";
+ RouterSwitchAllocator* sw_allocator = new RouterSwitchAllocator(sw_allocator_name, getTechModel());
+ sw_allocator->setParameter("NumberInputPorts", number_input_ports);
+ sw_allocator->setParameter("NumberOutputPorts", number_output_ports);
+ sw_allocator->setParameter("TotalNumberVirtualChannels", total_number_vcs);
+ sw_allocator->setParameter("ArbiterModel", arb_model);
+ sw_allocator->construct();
+
+ // Add the instance and the results
+ addSubInstances(sw_allocator, 1.0);
+ addElectricalSubResults(sw_allocator, 1.0);
+
+ // Create connections (currently connect CK only)
+ portConnect(sw_allocator, "CK", "CK");
+ return;
+ }
+
+ void Router::createCrossbar()
+ {
+ // Get parameters
+ const String& crossbar_model = getParameter("CrossbarModel");
+ unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
+ unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
+ unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
+ unsigned int number_input_port_outputs = getGenProperties()->get("InputPort->NumberOutputs").toUInt();
+
+ unsigned int number_crossbar_inputs = number_input_port_outputs * number_input_ports;
+ unsigned int number_crossbar_outputs = number_output_ports;
+ getGenProperties()->set("Crossbar->NumberInputs", number_crossbar_inputs);
+ getGenProperties()->set("Crossbar->NumberOutputs", number_crossbar_outputs);
+
+ // Init crossbar model
+ const String& crossbar_name = "Crossbar";
+ ElectricalModel* crossbar = ModelGen::createCrossbar(crossbar_model, crossbar_name, getTechModel());
+ crossbar->setParameter("NumberInputs", number_crossbar_inputs);
+ crossbar->setParameter("NumberOutputs", number_crossbar_outputs);
+ crossbar->setParameter("NumberBits", number_bits_per_flit);
+ crossbar->setParameter("BitDuplicate", "TRUE");
+ crossbar->construct();
+
+ unsigned int number_crossbar_selects = crossbar->getGenProperties()->get("NumberSelectsPerPort");
+ getGenProperties()->set("Crossbar->NumberSelects", number_crossbar_selects);
+
+ // Init DFF for crossbar selections
+ const String& crossbar_sel_dff_name = "Crossbar_Sel_DFF";
+ StdCell* crossbar_sel_dff = getTechModel()->getStdCellLib()->createStdCell("DFFQ", crossbar_sel_dff_name);
+ crossbar_sel_dff->construct();
+
+ // Add instances and results
+ addSubInstances(crossbar, 1.0);
+ addElectricalSubResults(crossbar, 1.0);
+
+ addSubInstances(crossbar_sel_dff, number_crossbar_outputs * number_crossbar_selects);
+ addElectricalSubResults(crossbar_sel_dff, number_crossbar_outputs * number_crossbar_selects);
+
+ // Create connections
+ createNet("Crossbar_Sel_DFF_Out");
+ for(unsigned int i = 0; i < number_crossbar_outputs; ++i)
+ {
+ for(unsigned int j = 0; j < number_crossbar_selects; ++j)
+ {
+ createNet(String::format("Crossbar_Sel%d_%d", i, j));
+ }
+ createNet("Crossbar_Out" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
+ }
+ for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
+ {
+ createNet("Crossbar_In" + (String)i, makeNetIndex(0, number_bits_per_flit-1));
+ }
+
+ for(unsigned int i = 0; i < number_crossbar_selects; ++i)
+ {
+ portConnect(crossbar_sel_dff, "CK", "CK");
+ }
+ portConnect(crossbar_sel_dff, "Q", "Crossbar_Sel_DFF_Out");
+ for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
+ {
+ assignVirtualFanout("Crossbar_In" + (String)i, "PipelineReg1_Out");
+ portConnect(crossbar, "In" + (String)i, "Crossbar_In" + (String)i);
+ }
+ for(unsigned int i = 0; i < number_crossbar_outputs; ++i)
+ {
+ for(unsigned int j = 0; j < number_crossbar_selects; ++j)
+ {
+ assignVirtualFanout(String::format("Crossbar_Sel%d_%d", i, j), "Crossbar_Sel_DFF_Out");
+ portConnect(crossbar, String::format("Sel%d_%d", i, j), String::format("Crossbar_Sel%d_%d", i, j));
+ }
+ portConnect(crossbar, "Out" + (String)i, "Crossbar_Out" + (String)i);
+ assignVirtualFanin("PipelineReg2_In" + (String)i, "Crossbar_Out" + (String)i);
+ }
+
+ return;
+ }
+
+ void Router::createPipelineReg()
+ {
+ // Get parameters
+ unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
+ unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
+ unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
+ unsigned int number_crossbar_inputs = getGenProperties()->get("Crossbar->NumberInputs");
+
+ // Init pipeline reg model
+ // First stage: from router input to input port
+ const String& pipeline_reg0_name = "PipelineReg0";
+ StdCell* pipeline_reg0 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg0_name);
+ pipeline_reg0->construct();
+ // Second stage: from input port to crossbar
+ const String& pipeline_reg1_name = "PipelineReg1";
+ StdCell* pipeline_reg1 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg1_name);
+ pipeline_reg1->construct();
+
+ // Third stage: from crossbar to router output
+ vector<StdCell*> pipeline_reg2s(number_output_ports, (StdCell*)NULL);
+ vector<String> pipeline_reg2_names(number_output_ports, "");
+ for(unsigned int i = 0; i < number_output_ports; ++i)
+ {
+ pipeline_reg2_names[i] = "PipelineReg2_" + (String)i;
+ pipeline_reg2s[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg2_names[i]);
+ pipeline_reg2s[i]->construct();
+ }
+
+ // Add instances and results
+ addSubInstances(pipeline_reg0, number_input_ports * number_bits_per_flit);
+ addElectricalSubResults(pipeline_reg0, number_input_ports * number_bits_per_flit);
+
+ addSubInstances(pipeline_reg1, number_crossbar_inputs * number_bits_per_flit);
+ addElectricalSubResults(pipeline_reg1, number_crossbar_inputs * number_bits_per_flit);
+
+ for(unsigned int i = 0; i < number_output_ports; ++i)
+ {
+ addSubInstances(pipeline_reg2s[i], number_bits_per_flit);
+ addElectricalSubResults(pipeline_reg2s[i], number_bits_per_flit);
+ }
+
+ // Create data connections
+ for(unsigned int i = 0; i < number_input_ports; ++i)
+ {
+ assignVirtualFanin("PipelineReg0_In", "FlitIn" + (String)i);
+ }
+ portConnect(pipeline_reg0, "D", "PipelineReg0_In");
+ portConnect(pipeline_reg0, "Q", "PipelineReg0_Out");
+ portConnect(pipeline_reg1, "D", "PipelineReg1_In");
+ portConnect(pipeline_reg1, "Q", "PipelineReg1_Out");
+ for(unsigned int i = 0; i < number_output_ports; ++i)
+ {
+ portConnect(pipeline_reg2s[i], "D", "PipelineReg2_In" + (String)i);
+ portConnect(pipeline_reg2s[i], "Q", "PipelineReg2_Out" + (String)i);
+ assignVirtualFanout("FlitOut" + (String)i, "PipelineReg2_Out" + (String)i);
+ }
+
+ // Create CK connections
+ for(unsigned int n = 0; n < number_bits_per_flit; ++n)
+ {
+ for(unsigned int i = 0; i < number_input_ports; ++i)
+ {
+ portConnect(pipeline_reg0, "CK", "CK");
+ }
+ for(unsigned int i = 0; i < number_crossbar_inputs; ++i)
+ {
+ portConnect(pipeline_reg1, "CK", "CK");
+ }
+ for(unsigned int i = 0; i < number_output_ports; ++i)
+ {
+ portConnect(pipeline_reg2s[i], "CK", "CK");
+ }
+ }
+ return;
+ }
+
+ void Router::createClockTree()
+ {
+ // Get parameters
+ const String& clock_tree_model = getParameter("ClockTreeModel");
+ const String& clock_tree_number_levels = getParameter("ClockTree->NumberLevels");
+ const String& clock_tree_wire_layer = getParameter("ClockTree->WireLayer");
+ const String& clock_tree_wire_width_multiplier = getParameter("ClockTree->WireWidthMultiplier");
+ const String& clock_tree_wire_spacing_multiplier = getParameter("ClockTree->WireSpacingMultiplier");
+
+ // Init clock tree model
+ const String& clock_tree_name = "ClockTree";
+ ElectricalModel* clock_tree = (ElectricalModel*)ModelGen::createModel(clock_tree_model, clock_tree_name, getTechModel());
+ clock_tree->setParameter("NumberLevels", clock_tree_number_levels);
+ clock_tree->setParameter("NumberBits", 1);
+ clock_tree->setParameter("WireLayer", clock_tree_wire_layer);
+ clock_tree->setParameter("WireWidthMultiplier", clock_tree_wire_width_multiplier);
+ clock_tree->setParameter("WireSpacingMultiplier", clock_tree_wire_spacing_multiplier);
+ clock_tree->construct();
+
+ // Add instances and results
+ addSubInstances(clock_tree, 1.0);
+ addElectricalSubResults(clock_tree, 1.0);
+
+ return;
+ }
+} // namespace DSENT
+
diff --git a/ext/dsent/model/electrical/router/Router.h b/ext/dsent/model/electrical/router/Router.h
new file mode 100644
index 000000000..c2c1df3bc
--- /dev/null
+++ b/ext/dsent/model/electrical/router/Router.h
@@ -0,0 +1,46 @@
+#ifndef __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_H__
+#define __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_H__
+
+#include "util/CommonType.h"
+#include "model/ElectricalModel.h"
+
+namespace DSENT
+{
+ /** \class Router
+ * \param Input ports: In[0-9]*
+ * \param Output ports: Out[0-9]*
+ */
+ class Router : public ElectricalModel
+ {
+ public:
+ Router(const String& instance_name_, const TechModel* tech_model_);
+ virtual ~Router();
+
+ public:
+ // Set a list of properties' name needed to construct model
+ void initParameters();
+ // Set a list of properties' name needed to construct model
+ void initProperties();
+
+ // Clone and return a new instance
+ virtual Router* clone() const;
+
+ protected:
+ // Build the model
+ virtual void constructModel();
+ virtual void updateModel();
+ virtual void propagateTransitionInfo();
+
+ private:
+ void createRouterInputPort();
+ void createVirtualChannelAllocator();
+ void createSwitchAllocator();
+ void createCrossbar();
+ void createClockTree();
+ void createPipelineReg();
+
+ }; // class Router
+} // namespace DSENT
+
+#endif // __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_H__
+
diff --git a/ext/dsent/model/electrical/router/RouterInputPort.cc b/ext/dsent/model/electrical/router/RouterInputPort.cc
new file mode 100644
index 000000000..b698d3d80
--- /dev/null
+++ b/ext/dsent/model/electrical/router/RouterInputPort.cc
@@ -0,0 +1,201 @@
+#include "model/electrical/router/RouterInputPort.h"
+
+#include <cmath>
+#include <vector>
+
+#include "model/PortInfo.h"
+#include "model/EventInfo.h"
+#include "model/TransitionInfo.h"
+#include "model/ModelGen.h"
+#include "model/std_cells/StdCellLib.h"
+#include "model/std_cells/StdCell.h"
+
+namespace DSENT
+{
+ using std::ceil;
+ using std::vector;
+ using LibUtil::castStringVector;
+
+ RouterInputPort::RouterInputPort(const String& instance_name_, const TechModel* tech_model_)
+ : ElectricalModel(instance_name_, tech_model_)
+ {
+ initParameters();
+ initProperties();
+ }
+
+ RouterInputPort::~RouterInputPort()
+ {}
+
+ void RouterInputPort::initParameters()
+ {
+ addParameterName("NumberVirtualNetworks");
+ addParameterName("NumberVirtualChannelsPerVirtualNetwork");
+ addParameterName("NumberBuffersPerVirtualChannel");
+ addParameterName("NumberBitsPerFlit");
+ addParameterName("BufferModel");
+ return;
+ }
+
+ void RouterInputPort::initProperties()
+ {
+ return;
+ }
+
+ RouterInputPort* RouterInputPort::clone() const
+ {
+ // TODO
+ return NULL;
+ }
+
+ void RouterInputPort::constructModel()
+ {
+ // Get parameters
+ unsigned int number_vns = getParameter("NumberVirtualNetworks").toUInt();
+ const vector<unsigned int>& number_vcs_per_vn_vector = castStringVector<unsigned int>(getParameter("NumberVirtualChannelsPerVirtualNetwork").split("[,]"));
+ const vector<unsigned int>& number_bufs_per_vc_vector = castStringVector<unsigned int>(getParameter("NumberBuffersPerVirtualChannel").split("[,]"));
+ unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt();
+ const String& buffer_model = getParameter("BufferModel");
+
+ ASSERT(number_vns > 0, "[Error] " + getInstanceName() +
+ " -> Number of virtual networks must be > 0!");
+ ASSERT(number_vcs_per_vn_vector.size() == number_vns, "[Error] " + getInstanceName() +
+ " -> Expecting " + (String)number_vns + " number of vcs, got " +
+ getParameter("NumberVirtualChannelsPerVirtualNetwork"));
+ for(unsigned int i = 0; i < number_vns; ++i)
+ {
+ ASSERT(number_vcs_per_vn_vector[i] > 0, "[Error] " + getInstanceName() +
+ " -> Number of virtual channels per virtual network must be > 0!");
+ }
+ ASSERT(number_bufs_per_vc_vector.size() == number_vns, "[Error] " + getInstanceName() +
+ " -> Expecting " + (String)number_vns + " number of bufs per vc, got " +
+ getParameter("NumberBuffersPerVirtualChannel"));
+ for(unsigned int i = 0; i < number_vns; ++i)
+ {
+ ASSERT(number_bufs_per_vc_vector[i] > 0, "[Error] " + getInstanceName() +
+ " -> Number of buffers per virtual channel must be > 0!");
+ }
+ ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() +
+ " -> Number of bits per buffer must be > 0!");
+
+ // Calculate total number of buffers needed in the RAM
+ unsigned int total_number_vcs = 0;
+ unsigned int total_number_bufs = 0;
+ for(unsigned int i = 0; i < number_vns; ++i)
+ {
+ total_number_vcs += number_vcs_per_vn_vector[i];
+ total_number_bufs += number_vcs_per_vn_vector[i] * number_bufs_per_vc_vector[i];
+ }
+ unsigned int number_addr_bits = (unsigned int)ceil(log2(total_number_bufs));
+
+ getGenProperties()->set("TotalNumberVirtualChannels", total_number_vcs);
+ getGenProperties()->set("TotalNumberBuffers", total_number_bufs);
+ getGenProperties()->set("NumberAddressBits", number_addr_bits);
+ getGenProperties()->set("NumberOutputs", 1);
+
+ createInputPort("CK");
+ createInputPort("FlitIn", makeNetIndex(0, number_bits_per_flit-1));
+ createOutputPort("FlitOut", makeNetIndex(0, number_bits_per_flit-1));
+
+ // Create energy, power, and area results
+ createElectricalResults();
+ getEventInfo("Idle")->setStaticTransitionInfos();
+ getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+
+ addEventResult(new Result("ReadBuffer"));
+ addEventResult(new Result("WriteBuffer"));
+
+ // Init RAM
+ const String& ram_name = "RAM";
+ ElectricalModel* ram = ModelGen::createRAM(buffer_model, ram_name, getTechModel());
+ ram->setParameter("NumberEntries", total_number_bufs);
+ ram->setParameter("NumberBits", number_bits_per_flit);
+ ram->construct();
+
+ // Init DFF for read address
+ vector<String> rd_addr_dff_names(number_addr_bits, "");
+ vector<StdCell*> rd_addr_dffs(number_addr_bits, NULL);
+ for(unsigned int i = 0; i < number_addr_bits; ++i)
+ {
+ rd_addr_dff_names[i] = "RDAddr_DFF" + (String)i;
+ rd_addr_dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", rd_addr_dff_names[i]);
+ rd_addr_dffs[i]->construct();
+ }
+
+ // Connect RDAddr_DFFs
+ for(unsigned int i = 0; i < number_addr_bits; ++i)
+ {
+ createNet("RDAddr_DFF_Out" + (String)i);
+
+ portConnect(rd_addr_dffs[i], "CK", "CK");
+ portConnect(rd_addr_dffs[i], "Q", "RDAddr_DFF_Out" + (String)i);
+ }
+
+ // Connect RAM
+ portConnect(ram, "In", "FlitIn");
+ for(unsigned int i = 0; i < number_addr_bits; ++i)
+ {
+ portConnect(ram, "WRAddr" + (String)i, "FlitIn", makeNetIndex(i));
+ portConnect(ram, "RDAddr" + (String)i, "RDAddr_DFF_Out" + (String)i);
+ }
+ portConnect(ram, "WE", "FlitIn", makeNetIndex(number_bits_per_flit-1));
+ portConnect(ram, "CK", "CK");
+ portConnect(ram, "Out", "FlitOut");
+
+ // Add area, power, event results
+ for(unsigned int i = 0; i < number_addr_bits; ++i)
+ {
+ addSubInstances(rd_addr_dffs[i], number_addr_bits);
+ addElectricalSubResults(rd_addr_dffs[i], number_addr_bits);
+ }
+ addSubInstances(ram, 1.0);
+ addElectricalSubResults(ram, 1.0);
+
+ getEventResult("WriteBuffer")->addSubResult(ram->getEventResult("Write"), ram_name, 1.0);
+
+ for(unsigned int i = 0; i < number_addr_bits; ++i)
+ {
+ getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("DFFD"), rd_addr_dff_names[i], number_addr_bits);
+ getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("DFFQ"), rd_addr_dff_names[i], number_addr_bits);
+ getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("CK"), rd_addr_dff_names[i], number_addr_bits);
+ }
+ getEventResult("ReadBuffer")->addSubResult(ram->getEventResult("Read"), ram_name, 1.0);
+
+ return;
+ }
+
+ void RouterInputPort::propagateTransitionInfo()
+ {
+ // Update probability and activity
+ unsigned int number_addr_bits = getGenProperties()->get("NumberAddressBits").toUInt();
+
+ vector<ElectricalModel*> rd_addr_dffs(number_addr_bits, NULL);
+ for(unsigned int i = 0; i < number_addr_bits; ++i)
+ {
+ rd_addr_dffs[i] = (ElectricalModel*)getSubInstance("RDAddr_DFF" + (String)i);
+ assignPortTransitionInfo(rd_addr_dffs[i], "D", TransitionInfo());
+ propagatePortTransitionInfo(rd_addr_dffs[i], "CK", "CK");
+ rd_addr_dffs[i]->use();
+ }
+
+ ElectricalModel* ram = (ElectricalModel*)getSubInstance("RAM");
+
+ // Setup default transition info
+ const String& current_event = getGenProperties()->get("UseModelEvent");
+ if(current_event != "Idle")
+ {
+ propagatePortTransitionInfo(ram, "In", "FlitIn");
+ propagatePortTransitionInfo(ram, "CK", "CK");
+ assignPortTransitionInfo(ram, "WE", TransitionInfo(0.0, 0.0, 1.0));
+ for(unsigned int i = 0; i < number_addr_bits; ++i)
+ {
+ assignPortTransitionInfo(ram, "WRAddr" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
+ assignPortTransitionInfo(ram, "RDAddr" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
+ }
+ }
+ ram->use();
+ // Set output probability
+ propagatePortTransitionInfo("FlitOut", ram, "Out");
+ return;
+ }
+} // namespace DSENT
+
diff --git a/ext/dsent/model/electrical/router/RouterInputPort.h b/ext/dsent/model/electrical/router/RouterInputPort.h
new file mode 100644
index 000000000..1d326a5cf
--- /dev/null
+++ b/ext/dsent/model/electrical/router/RouterInputPort.h
@@ -0,0 +1,33 @@
+#ifndef __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_INPUT_PORT_H__
+#define __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_INPUT_PORT_H__
+
+#include "util/CommonType.h"
+#include "model/ElectricalModel.h"
+
+namespace DSENT
+{
+ class RouterInputPort : public ElectricalModel
+ {
+ public:
+ RouterInputPort(const String& instance_name_, const TechModel* tech_model_);
+ virtual ~RouterInputPort();
+
+ public:
+ // Set a list of properties' name needed to construct model
+ void initParameters();
+ // Set a list of properties' name needed to construct model
+ void initProperties();
+
+ // Clone and return a new instance
+ virtual RouterInputPort* clone() const;
+
+ protected:
+ // Build the model
+ virtual void constructModel();
+ virtual void propagateTransitionInfo();
+
+ }; // class RouterInputPort
+} // namespace DSENT
+
+#endif // __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_INPUT_PORT_H__
+
diff --git a/ext/dsent/model/electrical/router/RouterSwitchAllocator.cc b/ext/dsent/model/electrical/router/RouterSwitchAllocator.cc
new file mode 100644
index 000000000..92e5431b1
--- /dev/null
+++ b/ext/dsent/model/electrical/router/RouterSwitchAllocator.cc
@@ -0,0 +1,199 @@
+#include "model/electrical/router/RouterSwitchAllocator.h"
+
+#include "model/PortInfo.h"
+#include "model/EventInfo.h"
+#include "model/TransitionInfo.h"
+#include "model/ModelGen.h"
+#include "model/std_cells/StdCell.h"
+#include "model/std_cells/StdCellLib.h"
+
+namespace DSENT
+{
+ RouterSwitchAllocator::RouterSwitchAllocator(const String& instance_name_, const TechModel* tech_model_)
+ : ElectricalModel(instance_name_, tech_model_)
+ {
+ initParameters();
+ initProperties();
+ }
+
+ RouterSwitchAllocator::~RouterSwitchAllocator()
+ {}
+
+ void RouterSwitchAllocator::initParameters()
+ {
+ addParameterName("NumberInputPorts");
+ addParameterName("NumberOutputPorts");
+ addParameterName("TotalNumberVirtualChannels");
+ addParameterName("ArbiterModel");
+ return;
+ }
+
+ void RouterSwitchAllocator::initProperties()
+ {}
+
+ RouterSwitchAllocator* RouterSwitchAllocator::clone() const
+ {
+ // TODO
+ return NULL;
+ }
+
+ void RouterSwitchAllocator::constructModel()
+ {
+ // Get parameters
+ unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt();
+ unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt();
+ unsigned int total_number_vcs = getParameter("TotalNumberVirtualChannels").toUInt();
+ const String& arb_model = getParameter("ArbiterModel");
+
+ ASSERT(number_input_ports > 0, "[Error] " + getInstanceName() +
+ " -> Number of input ports must be > 0!");
+ ASSERT(number_output_ports > 0, "[Error] " + getInstanceName() +
+ " -> Number of output ports must be > 0!");
+ ASSERT(total_number_vcs > 0, "[Error] " + getInstanceName() +
+ " -> Total number of virtual channels must be > 0!");
+
+ unsigned int stage1_number_requests = total_number_vcs;
+ unsigned int number_stage1_arbiters = number_input_ports;
+ unsigned int stage2_number_requests = number_input_ports;
+ unsigned int number_stage2_arbiters = number_output_ports;
+
+ getGenProperties()->set("NumberStage1Arbiters", number_stage1_arbiters);
+ getGenProperties()->set("Stage1->NumberRequests", stage1_number_requests);
+ getGenProperties()->set("NumberStage2Arbiters", number_stage2_arbiters);
+ getGenProperties()->set("Stage2->NumberRequests", stage2_number_requests);
+
+ // Create ports
+ createInputPort("CK");
+ for(unsigned int i = 0; i < number_stage1_arbiters; ++i)
+ {
+ for(unsigned int j = 0; j < stage1_number_requests; ++j)
+ {
+ createInputPort(String::format("Stage1Arb%d->Request%d", i, j));
+ createInputPort(String::format("Stage1Arb%d->Grant%d", i, j));
+ }
+ }
+ for(unsigned int i = 0; i < number_stage2_arbiters; ++i)
+ {
+ for(unsigned int j = 0; j < stage2_number_requests; ++j)
+ {
+ createInputPort(String::format("Stage2Arb%d->Request%d", i, j));
+ createInputPort(String::format("Stage2Arb%d->Grant%d", i, j));
+ }
+ }
+
+ // Create area, power, and event results
+ createElectricalResults();
+ getEventInfo("Idle")->setStaticTransitionInfos();
+ getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+
+ createElectricalEventResult("ArbitrateStage1");
+ getEventInfo("ArbitrateStage1")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+ createElectricalEventResult("ArbitrateStage2");
+ getEventInfo("ArbitrateStage2")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
+
+ // Init Stage1 arbiter
+ vector<String> stage1_arb_dff_names(stage1_number_requests, "");
+ vector<StdCell*> stage1_arb_dffs(stage1_number_requests, NULL);
+ for(unsigned int i = 0; i < stage1_number_requests; ++i)
+ {
+ stage1_arb_dff_names[i] = "Stage1ArbDFF" + (String)i;
+ stage1_arb_dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", stage1_arb_dff_names[i]);
+ stage1_arb_dffs[i]->construct();
+ }
+ const String& stage1_arb_name = "Stage1Arb";
+ ElectricalModel* stage1_arb = (ElectricalModel*)ModelGen::createModel(arb_model, stage1_arb_name, getTechModel());
+ stage1_arb->setParameter("NumberRequests", stage1_number_requests);
+ stage1_arb->construct();
+
+ // Init stage2 arbiter
+ vector<String> stage2_arb_dff_names(stage2_number_requests, "");
+ vector<StdCell*> stage2_arb_dffs(stage2_number_requests, NULL);
+ for(unsigned int i = 0; i < stage2_number_requests; ++i)
+ {
+ stage2_arb_dff_names[i] = "Stage2ArbDFF" + (String)i;
+ stage2_arb_dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", stage2_arb_dff_names[i]);
+ stage2_arb_dffs[i]->construct();
+ }
+ const String& stage2_arb_name = "Stage2Arb";
+ ElectricalModel* stage2_arb = (ElectricalModel*)ModelGen::createModel(arb_model, stage2_arb_name, getTechModel());
+ stage2_arb->setParameter("NumberRequests", stage2_number_requests);
+ stage2_arb->construct();
+
+ // Connect ports
+ for(unsigned int i = 0; i < stage1_number_requests; ++i)
+ {
+ const String& dff_in_name = "Stage1Arb_DFF_In" + (String)i;
+ const String& req_name = "Stage1Arb->Request" + (String)i;
+ const String& grant_name = "Stage1Arb->Grant" + (String)i;
+ createNet(dff_in_name);
+ createNet(req_name);
+ createNet(grant_name);
+ portConnect(stage1_arb_dffs[i], "D", dff_in_name);
+ portConnect(stage1_arb_dffs[i], "CK", "CK");
+ portConnect(stage1_arb_dffs[i], "Q", req_name);
+ portConnect(stage1_arb, "Request" + (String)i, req_name);
+ portConnect(stage1_arb, "Grant" + (String)i, grant_name);
+ for(unsigned int j = 0; j < number_stage1_arbiters; ++j)
+ {
+ assignVirtualFanin(dff_in_name, String::format("Stage1Arb%d->Request%d", j, i));
+ assignVirtualFanout(String::format("Stage1Arb%d->Grant%d", j, i), grant_name);
+ }
+ }
+ for(unsigned int i = 0; i < stage2_number_requests; ++i)
+ {
+ const String& dff_in_name = "Stage2Arb_DFF_In" + (String)i;
+ const String& req_name = "Stage2Arb->Request" + (String)i;
+ const String& grant_name = "Stage2Arb->Grant" + (String)i;
+ createNet(dff_in_name);
+ createNet(req_name);
+ createNet(grant_name);
+ portConnect(stage2_arb_dffs[i], "D", dff_in_name);
+ portConnect(stage2_arb_dffs[i], "CK", "CK");
+ portConnect(stage2_arb_dffs[i], "Q", req_name);
+ portConnect(stage2_arb, "Request" + (String)i, req_name);
+ portConnect(stage2_arb, "Grant" + (String)i, grant_name);
+ for(unsigned int j = 0; j < number_stage2_arbiters; ++j)
+ {
+ assignVirtualFanin(dff_in_name, String::format("Stage2Arb%d->Request%d", j, i));
+ assignVirtualFanout(String::format("Stage2Arb%d->Grant%d", j, i), grant_name);
+ }
+ }
+
+ // Add sub components
+ for(unsigned int i = 0; i < stage1_number_requests; ++i)
+ {
+ addSubInstances(stage1_arb_dffs[i], 1.0);
+ addElectricalSubResults(stage1_arb_dffs[i], 1.0);
+ }
+ addSubInstances(stage1_arb, number_stage1_arbiters);
+ addElectricalSubResults(stage1_arb, number_stage1_arbiters);
+ for(unsigned int i = 0; i < stage2_number_requests; ++i)
+ {
+ addSubInstances(stage2_arb_dffs[i], 1.0);
+ addElectricalSubResults(stage2_arb_dffs[i], 1.0);
+ }
+ addSubInstances(stage2_arb, number_stage2_arbiters);
+ addElectricalSubResults(stage2_arb, number_stage2_arbiters);
+
+ // Update stage1 arb arbitrate
+ getEventResult("ArbitrateStage1")->addSubResult(stage1_arb->getEventResult("Arbitrate"), stage1_arb_name, 1.0);
+
+ // Update stage2 arb arbitrate
+ getEventResult("ArbitrateStage2")->addSubResult(stage2_arb->getEventResult("Arbitrate"), stage2_arb_name, 1.0);
+ return;
+ }
+
+ void RouterSwitchAllocator::propagateTransitionInfo()
+ {
+ ElectricalModel* stage1_arb = (ElectricalModel*)getSubInstance("Stage1Arb");
+ stage1_arb->applyTransitionInfo("Arbitrate");
+ stage1_arb->use();
+
+ ElectricalModel* stage2_arb = (ElectricalModel*)getSubInstance("Stage2Arb");
+ stage2_arb->applyTransitionInfo("Arbitrate");
+ stage2_arb->use();
+
+ return;
+ }
+} // namespace DSENT
+
diff --git a/ext/dsent/model/electrical/router/RouterSwitchAllocator.h b/ext/dsent/model/electrical/router/RouterSwitchAllocator.h
new file mode 100644
index 000000000..8b18e199f
--- /dev/null
+++ b/ext/dsent/model/electrical/router/RouterSwitchAllocator.h
@@ -0,0 +1,33 @@
+#ifndef __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_SWITCH_ALLOCATOR_H__
+#define __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_SWITCH_ALLOCATOR_H__
+
+#include "util/CommonType.h"
+#include "model/ElectricalModel.h"
+
+namespace DSENT
+{
+ class RouterSwitchAllocator : public ElectricalModel
+ {
+ public:
+ RouterSwitchAllocator(const String& instance_name_, const TechModel* tech_model_);
+ virtual ~RouterSwitchAllocator();
+
+ public:
+ // Set a list of properties' name needed to construct model
+ void initParameters();
+ // Set a list of properties' name needed to construct model
+ void initProperties();
+
+ // Clone and return a new instance
+ virtual RouterSwitchAllocator* clone() const;
+
+ protected:
+ // Build the model
+ virtual void constructModel();
+ virtual void propagateTransitionInfo();
+
+ }; // RouterSwitchAllocator
+} // namespace DSENT
+
+#endif // __DSENT_MODEL_ELECTRICAL_ROUTER_ROUTER_SWITCH_ALLOCATOR_H__
+