diff options
author | Nilay Vaish <nilay@cs.wisc.edu> | 2014-10-11 15:02:23 -0500 |
---|---|---|
committer | Nilay Vaish <nilay@cs.wisc.edu> | 2014-10-11 15:02:23 -0500 |
commit | e8ed7b1d1b5bef31e9874f679a5797c2e00d06f1 (patch) | |
tree | 421c9c50377aa664958685914f5504c4c019e21f /ext/dsent/model/electrical/router | |
parent | a098fad174d8559037602b248b8e6f7f46bfebbb (diff) | |
download | gem5-e8ed7b1d1b5bef31e9874f679a5797c2e00d06f1.tar.xz |
ext: add the source code for DSENT
This patch adds a tool called DSENT to the ext/ directory. DSENT
is a tool that models power and area for on-chip networks. The next
patch adds a script for using the tool.
Diffstat (limited to 'ext/dsent/model/electrical/router')
-rw-r--r-- | ext/dsent/model/electrical/router/Router.cc | 536 | ||||
-rw-r--r-- | ext/dsent/model/electrical/router/Router.h | 46 | ||||
-rw-r--r-- | ext/dsent/model/electrical/router/RouterInputPort.cc | 201 | ||||
-rw-r--r-- | ext/dsent/model/electrical/router/RouterInputPort.h | 33 | ||||
-rw-r--r-- | ext/dsent/model/electrical/router/RouterSwitchAllocator.cc | 199 | ||||
-rw-r--r-- | ext/dsent/model/electrical/router/RouterSwitchAllocator.h | 33 |
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__ + |