#include "model/electrical/router/RouterInputPort.h" #include #include #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& number_vcs_per_vn_vector = castStringVector(getParameter("NumberVirtualChannelsPerVirtualNetwork").split("[,]")); const vector& number_bufs_per_vc_vector = castStringVector(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 rd_addr_dff_names(number_addr_bits, ""); vector 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 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