1/* Copyright (c) 2012 Massachusetts Institute of Technology 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to deal 5 * in the Software without restriction, including without limitation the rights 6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 * copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 * THE SOFTWARE. 20 */ 21 22#include "model/electrical/router/RouterInputPort.h" 23 24#include <cmath> 25#include <vector> 26 27#include "model/PortInfo.h" 28#include "model/EventInfo.h" 29#include "model/TransitionInfo.h" 30#include "model/ModelGen.h" 31#include "model/std_cells/StdCellLib.h" 32#include "model/std_cells/StdCell.h" 33 34namespace DSENT 35{ 36 using std::ceil; 37 using std::vector; 38 using LibUtil::castStringVector; 39 40 RouterInputPort::RouterInputPort(const String& instance_name_, const TechModel* tech_model_) 41 : ElectricalModel(instance_name_, tech_model_) 42 { 43 initParameters(); 44 initProperties(); 45 } 46 47 RouterInputPort::~RouterInputPort() 48 {} 49 50 void RouterInputPort::initParameters() 51 { 52 addParameterName("NumberVirtualNetworks"); 53 addParameterName("NumberVirtualChannelsPerVirtualNetwork"); 54 addParameterName("NumberBuffersPerVirtualChannel"); 55 addParameterName("NumberBitsPerFlit"); 56 addParameterName("BufferModel"); 57 return; 58 } 59 60 void RouterInputPort::initProperties() 61 { 62 return; 63 } 64 65 RouterInputPort* RouterInputPort::clone() const 66 { 67 // TODO 68 return NULL; 69 } 70 71 void RouterInputPort::constructModel() 72 { 73 // Get parameters 74 unsigned int number_vns = getParameter("NumberVirtualNetworks").toUInt(); 75 const vector<unsigned int>& number_vcs_per_vn_vector = castStringVector<unsigned int>(getParameter("NumberVirtualChannelsPerVirtualNetwork").split("[,]")); 76 const vector<unsigned int>& number_bufs_per_vc_vector = castStringVector<unsigned int>(getParameter("NumberBuffersPerVirtualChannel").split("[,]")); 77 unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt(); 78 const String& buffer_model = getParameter("BufferModel"); 79 80 ASSERT(number_vns > 0, "[Error] " + getInstanceName() + 81 " -> Number of virtual networks must be > 0!"); 82 ASSERT(number_vcs_per_vn_vector.size() == number_vns, "[Error] " + getInstanceName() + 83 " -> Expecting " + (String)number_vns + " number of vcs, got " + 84 getParameter("NumberVirtualChannelsPerVirtualNetwork")); 85 for(unsigned int i = 0; i < number_vns; ++i) 86 { 87 ASSERT(number_vcs_per_vn_vector[i] > 0, "[Error] " + getInstanceName() + 88 " -> Number of virtual channels per virtual network must be > 0!"); 89 } 90 ASSERT(number_bufs_per_vc_vector.size() == number_vns, "[Error] " + getInstanceName() + 91 " -> Expecting " + (String)number_vns + " number of bufs per vc, got " + 92 getParameter("NumberBuffersPerVirtualChannel")); 93 for(unsigned int i = 0; i < number_vns; ++i) 94 { 95 ASSERT(number_bufs_per_vc_vector[i] > 0, "[Error] " + getInstanceName() + 96 " -> Number of buffers per virtual channel must be > 0!"); 97 } 98 ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() + 99 " -> Number of bits per buffer must be > 0!"); 100 101 // Calculate total number of buffers needed in the RAM 102 unsigned int total_number_vcs = 0; 103 unsigned int total_number_bufs = 0; 104 for(unsigned int i = 0; i < number_vns; ++i) 105 { 106 total_number_vcs += number_vcs_per_vn_vector[i]; 107 total_number_bufs += number_vcs_per_vn_vector[i] * number_bufs_per_vc_vector[i]; 108 } 109 unsigned int number_addr_bits = (unsigned int)ceil(log2(total_number_bufs)); 110 111 getGenProperties()->set("TotalNumberVirtualChannels", total_number_vcs); 112 getGenProperties()->set("TotalNumberBuffers", total_number_bufs); 113 getGenProperties()->set("NumberAddressBits", number_addr_bits); 114 getGenProperties()->set("NumberOutputs", 1); 115 116 createInputPort("CK"); 117 createInputPort("FlitIn", makeNetIndex(0, number_bits_per_flit-1)); 118 createOutputPort("FlitOut", makeNetIndex(0, number_bits_per_flit-1)); 119 120 // Create energy, power, and area results 121 createElectricalResults(); 122 getEventInfo("Idle")->setStaticTransitionInfos(); 123 getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 124 125 addEventResult(new Result("ReadBuffer")); 126 addEventResult(new Result("WriteBuffer")); 127 128 // Init RAM 129 const String& ram_name = "RAM"; 130 ElectricalModel* ram = ModelGen::createRAM(buffer_model, ram_name, getTechModel()); 131 ram->setParameter("NumberEntries", total_number_bufs); 132 ram->setParameter("NumberBits", number_bits_per_flit); 133 ram->construct(); 134 135 // Init DFF for read address 136 vector<String> rd_addr_dff_names(number_addr_bits, ""); 137 vector<StdCell*> rd_addr_dffs(number_addr_bits, NULL); 138 for(unsigned int i = 0; i < number_addr_bits; ++i) 139 { 140 rd_addr_dff_names[i] = "RDAddr_DFF" + (String)i; 141 rd_addr_dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", rd_addr_dff_names[i]); 142 rd_addr_dffs[i]->construct(); 143 } 144 145 // Connect RDAddr_DFFs 146 for(unsigned int i = 0; i < number_addr_bits; ++i) 147 { 148 createNet("RDAddr_DFF_Out" + (String)i); 149 150 portConnect(rd_addr_dffs[i], "CK", "CK"); 151 portConnect(rd_addr_dffs[i], "Q", "RDAddr_DFF_Out" + (String)i); 152 } 153 154 // Connect RAM 155 portConnect(ram, "In", "FlitIn"); 156 for(unsigned int i = 0; i < number_addr_bits; ++i) 157 { 158 portConnect(ram, "WRAddr" + (String)i, "FlitIn", makeNetIndex(i)); 159 portConnect(ram, "RDAddr" + (String)i, "RDAddr_DFF_Out" + (String)i); 160 } 161 portConnect(ram, "WE", "FlitIn", makeNetIndex(number_bits_per_flit-1)); 162 portConnect(ram, "CK", "CK"); 163 portConnect(ram, "Out", "FlitOut"); 164 165 // Add area, power, event results 166 for(unsigned int i = 0; i < number_addr_bits; ++i) 167 { 168 addSubInstances(rd_addr_dffs[i], number_addr_bits); 169 addElectricalSubResults(rd_addr_dffs[i], number_addr_bits); 170 } 171 addSubInstances(ram, 1.0); 172 addElectricalSubResults(ram, 1.0); 173 174 getEventResult("WriteBuffer")->addSubResult(ram->getEventResult("Write"), ram_name, 1.0); 175 176 for(unsigned int i = 0; i < number_addr_bits; ++i) 177 { 178 getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("DFFD"), rd_addr_dff_names[i], number_addr_bits); 179 getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("DFFQ"), rd_addr_dff_names[i], number_addr_bits); 180 getEventResult("ReadBuffer")->addSubResult(rd_addr_dffs[i]->getEventResult("CK"), rd_addr_dff_names[i], number_addr_bits); 181 } 182 getEventResult("ReadBuffer")->addSubResult(ram->getEventResult("Read"), ram_name, 1.0); 183 184 return; 185 } 186 187 void RouterInputPort::propagateTransitionInfo() 188 { 189 // Update probability and activity 190 unsigned int number_addr_bits = getGenProperties()->get("NumberAddressBits").toUInt(); 191 192 vector<ElectricalModel*> rd_addr_dffs(number_addr_bits, NULL); 193 for(unsigned int i = 0; i < number_addr_bits; ++i) 194 { 195 rd_addr_dffs[i] = (ElectricalModel*)getSubInstance("RDAddr_DFF" + (String)i); 196 assignPortTransitionInfo(rd_addr_dffs[i], "D", TransitionInfo()); 197 propagatePortTransitionInfo(rd_addr_dffs[i], "CK", "CK"); 198 rd_addr_dffs[i]->use(); 199 } 200 201 ElectricalModel* ram = (ElectricalModel*)getSubInstance("RAM"); 202 203 // Setup default transition info 204 const String& current_event = getGenProperties()->get("UseModelEvent"); 205 if(current_event != "Idle") 206 { 207 propagatePortTransitionInfo(ram, "In", "FlitIn"); 208 propagatePortTransitionInfo(ram, "CK", "CK"); 209 assignPortTransitionInfo(ram, "WE", TransitionInfo(0.0, 0.0, 1.0)); 210 for(unsigned int i = 0; i < number_addr_bits; ++i) 211 { 212 assignPortTransitionInfo(ram, "WRAddr" + (String)i, TransitionInfo(0.25, 0.25, 0.25)); 213 assignPortTransitionInfo(ram, "RDAddr" + (String)i, TransitionInfo(0.25, 0.25, 0.25)); 214 } 215 } 216 ram->use(); 217 // Set output probability 218 propagatePortTransitionInfo("FlitOut", ram, "Out"); 219 return; 220 } 221} // namespace DSENT 222 223