summaryrefslogtreecommitdiff
path: root/ext/dsent/model/electrical/router/RouterInputPort.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dsent/model/electrical/router/RouterInputPort.cc')
-rw-r--r--ext/dsent/model/electrical/router/RouterInputPort.cc201
1 files changed, 201 insertions, 0 deletions
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
+