ElectricalMesh.cc revision 10447
1#include "model/network/ElectricalMesh.h" 2 3#include <cmath> 4 5#include "model/PortInfo.h" 6#include "model/EventInfo.h" 7#include "model/TransitionInfo.h" 8#include "model/ModelGen.h" 9#include "model/std_cells/StdCellLib.h" 10#include "model/timing_graph/ElectricalTimingTree.h" 11#include "model/timing_graph/ElectricalNet.h" 12 13namespace DSENT 14{ 15 using std::sqrt; 16 17 ElectricalMesh::ElectricalMesh(const String& instance_name_, const TechModel* tech_model_) 18 : ElectricalModel(instance_name_, tech_model_) 19 { 20 initParameters(); 21 initProperties(); 22 } 23 24 ElectricalMesh::~ElectricalMesh() 25 {} 26 27 void ElectricalMesh::initParameters() 28 { 29 // Clock Frequency 30 addParameterName("Frequency"); 31 // Physical Parameters 32 addParameterName("NumberSites"); 33 addParameterName("NumberBitsPerFlit"); 34 // Concentration factor 35 addParameterName("NumberSitesPerRouter"); 36 // Router parameters 37 addParameterName("Router->NumberVirtualNetworks"); 38 addParameterName("Router->NumberVirtualChannelsPerVirtualNetwork"); 39 addParameterName("Router->NumberBuffersPerVirtualChannel"); 40 addParameterName("Router->InputPort->BufferModel"); 41 addParameterName("Router->CrossbarModel"); 42 addParameterName("Router->SwitchAllocator->ArbiterModel"); 43 addParameterName("Router->ClockTreeModel"); 44 addParameterName("Router->ClockTree->NumberLevels"); 45 addParameterName("Router->ClockTree->WireLayer"); 46 addParameterName("Router->ClockTree->WireWidthMultiplier"); 47 addParameterName("Router->ClockTree->WireSpacingMultiplier", 3.0); 48 // Link parameters 49 addParameterName("Link->WireLayer"); 50 addParameterName("Link->WireWidthMultiplier"); 51 addParameterName("Link->WireSpacingMultiplier"); 52 return; 53 } 54 55 void ElectricalMesh::initProperties() 56 { 57 addPropertyName("SitePitch"); 58 return; 59 } 60 61 ElectricalMesh* ElectricalMesh::clone() const 62 { 63 // TODO 64 return NULL; 65 } 66 67 void ElectricalMesh::constructModel() 68 { 69 // Get input paramters 70 unsigned int number_sites = getParameter("NumberSites").toUInt(); 71 unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt(); 72 unsigned int number_sites_per_router = getParameter("NumberSitesPerRouter").toUInt(); 73 74 ASSERT(number_sites > 0, "[Error] " + getInstanceName() + 75 " -> Number of sites must be > 0!"); 76 ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() + 77 " -> Number of bits per flit must be > 0!"); 78 ASSERT(number_sites_per_router > 0, "[Error] " + getInstanceName() + 79 " -> Number of sites per router must be > 0!"); 80 81 // Get input parameters that will be forwarded to the sub instances 82 const String& router_number_vns = getParameter("Router->NumberVirtualNetworks"); 83 const String& router_number_vcs_per_vn = getParameter("Router->NumberVirtualChannelsPerVirtualNetwork"); 84 const String& router_number_bufs_per_vc = getParameter("Router->NumberBuffersPerVirtualChannel"); 85 const String& link_wire_layer = getParameter("Link->WireLayer"); 86 const String& link_wire_width_multiplier = getParameter("Link->WireWidthMultiplier"); 87 const String& link_wire_spacing_multiplier = getParameter("Link->WireSpacingMultiplier"); 88 89 // Calculate properties from input parameters 90 unsigned int number_routers = number_sites / number_sites_per_router; 91 unsigned int number_router_to_router_links = 4 * number_routers; 92 unsigned int number_router_to_site_links = 2 * number_sites; 93 unsigned int router_number_input_ports = 4 + number_sites_per_router; 94 unsigned int router_number_output_ports = 4 + number_sites_per_router; 95 96 getGenProperties()->set("NumberRouters", number_routers); 97 getGenProperties()->set("NumberRouterToRouterLinks", number_router_to_router_links); 98 getGenProperties()->set("NumberRouterToSiteLinks", number_router_to_site_links); 99 getGenProperties()->set("Router->NumberInputPorts", router_number_input_ports); 100 getGenProperties()->set("Router->NumberOutputPorts", router_number_output_ports); 101 102 // Create ports 103 createInputPort("CK"); 104 105 // Init mesh routers 106 ElectricalModel* router = (ElectricalModel*)ModelGen::createModel("Router", "MeshRouter", getTechModel()); 107 router->setParameter("NumberInputPorts", router_number_input_ports); 108 router->setParameter("NumberOutputPorts", router_number_output_ports); 109 router->setParameter("NumberVirtualNetworks", router_number_vns); 110 router->setParameter("NumberVirtualChannelsPerVirtualNetwork", router_number_vcs_per_vn); 111 router->setParameter("NumberBuffersPerVirtualChannel", router_number_bufs_per_vc); 112 router->setParameter("NumberBitsPerFlit", number_bits_per_flit); 113 router->setParameter("InputPort->BufferModel", getParameter("Router->InputPort->BufferModel")); 114 router->setParameter("CrossbarModel", getParameter("Router->CrossbarModel")); 115 router->setParameter("SwitchAllocator->ArbiterModel", getParameter("Router->SwitchAllocator->ArbiterModel")); 116 router->setParameter("ClockTreeModel", getParameter("Router->ClockTreeModel")); 117 router->setParameter("ClockTree->NumberLevels", getParameter("Router->ClockTree->NumberLevels")); 118 router->setParameter("ClockTree->WireLayer", getParameter("Router->ClockTree->WireLayer")); 119 router->setParameter("ClockTree->WireWidthMultiplier", getParameter("Router->ClockTree->WireWidthMultiplier")); 120 router->setParameter("ClockTree->WireSpacingMultiplier", getParameter("Router->ClockTree->WireSpacingMultiplier")); 121 router->construct(); 122 123 // Init router to router links 124 ElectricalModel* rr_link = (ElectricalModel*)ModelGen::createModel("RepeatedLink", "RouterToRouterLink", getTechModel()); 125 rr_link->setParameter("NumberBits", number_bits_per_flit); 126 rr_link->setParameter("WireLayer", link_wire_layer); 127 rr_link->setParameter("WireWidthMultiplier", link_wire_width_multiplier); 128 rr_link->setParameter("WireSpacingMultiplier", link_wire_spacing_multiplier); 129 rr_link->construct(); 130 131 // Init router to site links 132 ElectricalModel* rs_link = (ElectricalModel*)ModelGen::createModel("RepeatedLink", "RouterToSiteLink", getTechModel()); 133 rs_link->setParameter("NumberBits", number_bits_per_flit); 134 rs_link->setParameter("WireLayer", link_wire_layer); 135 rs_link->setParameter("WireWidthMultiplier", link_wire_width_multiplier); 136 rs_link->setParameter("WireSpacingMultiplier", link_wire_spacing_multiplier); 137 rs_link->construct(); 138 139 // Connect ports 140 createNet("RR_Link_Out", makeNetIndex(0, number_bits_per_flit-1)); 141 createNet("RR_Link_In", makeNetIndex(0, number_bits_per_flit-1)); 142 portConnect(rr_link, "In", "RR_Link_In"); 143 portConnect(rr_link, "Out", "RR_Link_Out"); 144 145 createNet("RS_Link_Out", makeNetIndex(0, number_bits_per_flit-1)); 146 createNet("RS_Link_In", makeNetIndex(0, number_bits_per_flit-1)); 147 portConnect(rs_link, "In", "RS_Link_In"); 148 portConnect(rs_link, "Out", "RS_Link_Out"); 149 150 portConnect(router, "CK", "CK"); 151 for(unsigned int i = 0; i < router_number_input_ports; ++i) 152 { 153 createNet("Router_In" + (String)i, makeNetIndex(0, number_bits_per_flit-1)); 154 portConnect(router, "FlitIn" + (String)i, "Router_In" + (String)i); 155 } 156 for(unsigned int i = 0; i < router_number_output_ports; ++i) 157 { 158 createNet("Router_Out" + (String)i, makeNetIndex(0, number_bits_per_flit-1)); 159 portConnect(router, "FlitOut" + (String)i, "Router_Out" + (String)i); 160 } 161 for(unsigned int i = 0; i < number_bits_per_flit; ++i) 162 { 163 for(unsigned int j = 0; j < 4; ++j) 164 { 165 assignVirtualFanout("Router_In" + (String)j, makeNetIndex(i), "RR_Link_Out", makeNetIndex(i)); 166 assignVirtualFanin("RR_Link_In", makeNetIndex(i), "Router_Out" + (String)j, makeNetIndex(i)); 167 } 168 for(unsigned int j = 4; j < router_number_input_ports; ++j) 169 { 170 assignVirtualFanout("Router_In" + (String)j, makeNetIndex(i), "RS_Link_Out", makeNetIndex(i)); 171 assignVirtualFanin("RS_Link_In", makeNetIndex(i), "Router_Out" + (String)j, makeNetIndex(i)); 172 } 173 } 174 175 // Create area, power and event results 176 createElectricalResults(); 177 createElectricalEventResult("AvgUnicast"); 178 createElectricalEventResult("AvgBroadcast"); 179 180 // Add all instances 181 addSubInstances(router, number_routers); 182 addElectricalSubResults(router, number_routers); 183 addSubInstances(rr_link, number_router_to_router_links); 184 addElectricalSubResults(rr_link, number_router_to_router_links); 185 addSubInstances(rs_link, number_router_to_site_links); 186 addElectricalSubResults(rs_link, number_router_to_site_links); 187 188 double number_routers_per_side = sqrt(number_routers); 189 190 // Update unicast event 191 double avg_number_unicast_hop = 2.0 * number_routers_per_side / 3.0; 192 double avg_number_unicast_rr_links_traveled = avg_number_unicast_hop; 193 double avg_number_unicast_rs_links_traveled = 2.0; 194 double avg_number_unicast_router_traveled = avg_number_unicast_hop + 1.0; 195 Result* avg_unicast_flit = getEventResult("AvgUnicast"); 196 avg_unicast_flit->addSubResult(rr_link->getEventResult("Send"), "RouterToRouterLink", avg_number_unicast_rr_links_traveled); 197 avg_unicast_flit->addSubResult(rs_link->getEventResult("Send"), "RouterToSiteLink", avg_number_unicast_rs_links_traveled); 198 if(router->hasEventResult("WriteBuffer")) 199 { 200 avg_unicast_flit->addSubResult(router->getEventResult("WriteBuffer"), "MeshRouter", avg_number_unicast_router_traveled); 201 } 202 if(router->hasEventResult("ReadBuffer")) 203 { 204 avg_unicast_flit->addSubResult(router->getEventResult("ReadBuffer"), "MeshRouter", avg_number_unicast_router_traveled); 205 } 206 avg_unicast_flit->addSubResult(router->getEventResult("TraverseCrossbar->Multicast1"), "MeshRouter", avg_number_unicast_router_traveled); 207 208 // Update broadcast event 209 double avg_number_broadcast_rr_links_traveled = (number_routers_per_side - 1.0) * number_routers_per_side + number_routers_per_side - 1.0; 210 double avg_number_broadcast_rs_links_traveled = number_sites; 211 double avg_number_broadcast_router_crossbar_traveled = number_routers * (number_sites_per_router + 1.0) - 2.0; 212 Result* avg_broadcast_flit = getEventResult("AvgBroadcast"); 213 avg_broadcast_flit->addSubResult(rr_link->getEventResult("Send"), "RouterToRouterLink", avg_number_broadcast_rr_links_traveled); 214 avg_broadcast_flit->addSubResult(rs_link->getEventResult("Send"), "RouterToSiteLink", avg_number_broadcast_rs_links_traveled); 215 if(router->hasEventResult("WriteBuffer")) 216 { 217 avg_broadcast_flit->addSubResult(router->getEventResult("WriteBuffer"), "MeshRouter", number_routers); 218 } 219 if(router->hasEventResult("ReadBuffer")) 220 { 221 avg_broadcast_flit->addSubResult(router->getEventResult("ReadBuffer"), "MeshRouter", number_routers); 222 } 223 avg_broadcast_flit->addSubResult(router->getEventResult("TraverseCrossbar->Multicast1"), "MeshRouter", avg_number_broadcast_router_crossbar_traveled); 224 225 return; 226 } 227 228 void ElectricalMesh::updateModel() 229 { 230 // Get properties 231 double site_pitch = getProperty("SitePitch").toDouble(); 232 double clock_freq = getParameter("Frequency"); 233 234 ASSERT(site_pitch > 0, "[Error] " + getInstanceName() + 235 " -> Site pitch must be > 0!"); 236 ASSERT(clock_freq > 0, "[Error] " + getInstanceName() + 237 " -> Clock frequency must be > 0!"); 238 239 unsigned int number_sites_per_router = getParameter("NumberSitesPerRouter"); 240 // Get margin on link delays, since there are registers before and after the link 241 double delay_ck_to_q = getTechModel()->getStdCellLib()->getStdCellCache()->get("DFFQ_X1->Delay->CK_to_Q"); 242 double delay_setup = getTechModel()->getStdCellLib()->getStdCellCache()->get("DFFQ_X1->Delay->CK_to_Q"); 243 double link_delay_margin = (delay_ck_to_q + delay_setup) * 1.5; 244 245 double rr_link_length = site_pitch * sqrt(number_sites_per_router); 246 double rr_link_delay = std::max(1e-99, 1.0 / clock_freq - link_delay_margin); 247 double rs_link_length = site_pitch * (sqrt(number_sites_per_router) - 1.0); 248 double rs_link_delay = std::max(1e-99, 1.0 / clock_freq - link_delay_margin ); 249 double router_delay = 1.0 / clock_freq; 250 251 Model* rr_link = getSubInstance("RouterToRouterLink"); 252 rr_link->setProperty("WireLength", rr_link_length); 253 rr_link->setProperty("Delay", rr_link_delay); 254 rr_link->setProperty("IsKeepParity", "TRUE"); 255 rr_link->update(); 256 257 Model* rs_link = getSubInstance("RouterToSiteLink"); 258 rs_link->setProperty("WireLength", rs_link_length); 259 rs_link->setProperty("Delay", rs_link_delay); 260 rs_link->setProperty("IsKeepParity", "TRUE"); 261 rs_link->update(); 262 263 ElectricalModel* router = (ElectricalModel*)getSubInstance("MeshRouter"); 264 router->update(); 265 266 ElectricalTimingTree router_timing_tree("MeshRouter", router); 267 router_timing_tree.performTimingOpt(router->getNet("CK"), router_delay); 268 return; 269 } 270 271 void ElectricalMesh::propagateTransitionInfo() 272 { 273 // Get parameters 274 unsigned int router_number_input_ports = getGenProperties()->get("Router->NumberInputPorts"); 275 276 ElectricalModel* rr_link = (ElectricalModel*)getSubInstance("RouterToRouterLink"); 277 assignPortTransitionInfo(rr_link, "In", TransitionInfo(0.25, 0.25, 0.25)); 278 rr_link->use(); 279 280 ElectricalModel* rs_link = (ElectricalModel*)getSubInstance("RouterToSiteLink"); 281 assignPortTransitionInfo(rs_link, "In", TransitionInfo(0.25, 0.25, 0.25)); 282 rs_link->use(); 283 284 ElectricalModel* router = (ElectricalModel*)getSubInstance("MeshRouter"); 285 for(unsigned int i = 0; i < router_number_input_ports; ++i) 286 { 287 assignPortTransitionInfo(router, "FlitIn" + (String)i, TransitionInfo(0.25, 0.25, 0.25)); 288 } 289 assignPortTransitionInfo(router, "CK", TransitionInfo(0.0, 1.0, 0.0)); 290 router->getGenProperties()->set("UseModelEvent", ""); 291 router->use(); 292 293 return; 294 } 295} // namespace DSENT 296 297