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/Router.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#include "model/electrical/router/RouterInputPort.h" 34#include "model/electrical/router/RouterSwitchAllocator.h" 35#include "model/timing_graph/ElectricalNet.h" 36 37namespace DSENT 38{ 39 using std::sqrt; 40 using std::vector; 41 42 using LibUtil::castStringVector; 43 using LibUtil::vectorToString; 44 45 Router::Router(const String& instance_name_, const TechModel* tech_model_) 46 : ElectricalModel(instance_name_, tech_model_) 47 { 48 initParameters(); 49 initProperties(); 50 } 51 52 Router::~Router() 53 {} 54 55 void Router::initParameters() 56 { 57 addParameterName("NumberInputPorts"); 58 addParameterName("NumberOutputPorts"); 59 addParameterName("NumberBitsPerFlit"); 60 addParameterName("NumberVirtualNetworks"); 61 addParameterName("NumberVirtualChannelsPerVirtualNetwork"); 62 addParameterName("NumberBuffersPerVirtualChannel"); 63 // Spec for input port 64 addParameterName("InputPort->BufferModel"); 65 // Spec for crossbar 66 addParameterName("CrossbarModel"); 67 // Spec for switch allocator 68 addParameterName("SwitchAllocator->ArbiterModel"); 69 // Spec for clock tree 70 addParameterName("ClockTreeModel"); 71 addParameterName("ClockTree->NumberLevels"); 72 addParameterName("ClockTree->WireLayer"); 73 addParameterName("ClockTree->WireWidthMultiplier"); 74 addParameterName("ClockTree->WireSpacingMultiplier", 3.0); 75 return; 76 } 77 78 void Router::initProperties() 79 { 80 return; 81 } 82 83 Router* Router::clone() const 84 { 85 // TODO 86 return NULL; 87 } 88 89 void Router::constructModel() 90 { 91 // Get parameters 92 unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt(); 93 unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt(); 94 unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt(); 95 96 ASSERT(number_input_ports > 0, "[Error] " + getInstanceName() + 97 " -> Number of input ports must be > 0!"); 98 ASSERT(number_output_ports > 0, "[Error] " + getInstanceName() + 99 " -> Number of output ports must be > 0!"); 100 ASSERT(number_bits_per_flit > 0, "[Error] " + getInstanceName() + 101 " -> Number of bits per buffer must be > 0!"); 102 103 // Create ports 104 createInputPort("CK"); 105 for(unsigned int i = 0; i < number_input_ports; ++i) 106 { 107 createInputPort("FlitIn" + (String)i, makeNetIndex(0, number_bits_per_flit-1)); 108 } 109 for(unsigned int i = 0; i < number_output_ports; ++i) 110 { 111 createOutputPort("FlitOut" + (String)i, makeNetIndex(0, number_bits_per_flit-1)); 112 } 113 114 // Create area, power, event results 115 createElectricalResults(); 116 getEventInfo("Idle")->setStaticTransitionInfos(); 117 getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 118 119 createElectricalEventResult("ReadBuffer"); 120 getEventInfo("ReadBuffer")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 121 createElectricalEventResult("WriteBuffer"); 122 getEventInfo("WriteBuffer")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 123 for(unsigned int i = 1; i <= number_output_ports; ++i) 124 { 125 createElectricalEventResult("TraverseCrossbar->Multicast" + (String)i); 126 getEventInfo("TraverseCrossbar->Multicast" + (String)i)->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 127 } 128 createElectricalEventResult("ArbitrateSwitch->ArbitrateStage1"); 129 createElectricalEventResult("ArbitrateSwitch->ArbitrateStage2"); 130 createElectricalEventResult("DistributeClock"); 131 getEventInfo("DistributeClock")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 132 133 // Create intermediate nets 134 createNet("PipelineReg0_In"); 135 createNet("PipelineReg0_Out"); 136 createNet("PipelineReg1_In"); 137 createNet("PipelineReg1_Out"); 138 for(unsigned int i = 0; i < number_output_ports; ++i) 139 { 140 createNet("PipelineReg2_In" + (String)i); 141 createNet("PipelineReg2_Out" + (String)i); 142 } 143 144 createRouterInputPort(); 145 createSwitchAllocator(); 146 createVirtualChannelAllocator(); 147 createCrossbar(); 148 createClockTree(); 149 createPipelineReg(); 150 151 // Get generated numbers 152 unsigned int number_crossbar_selects = getGenProperties()->get("Crossbar->NumberSelects"); 153 154 // Add write buffer event 155 getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("DFFD"), "PipelineReg0", number_bits_per_flit); 156 getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("DFFQ"), "PipelineReg0", number_bits_per_flit); 157 getEventResult("WriteBuffer")->addSubResult(getSubInstance("PipelineReg0")->getEventResult("CK"), "PipelineReg0", number_bits_per_flit); 158 getEventResult("WriteBuffer")->addSubResult(getSubInstance("InputPort")->getEventResult("WriteBuffer"), "InputPort", 1.0); 159 160 // Add read buffer event 161 getEventResult("ReadBuffer")->addSubResult(getSubInstance("InputPort")->getEventResult("ReadBuffer"), "InputPort", 1.0); 162 getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("DFFD"), "PipelineReg1", number_bits_per_flit); 163 getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("DFFQ"), "PipelineReg1", number_bits_per_flit); 164 getEventResult("ReadBuffer")->addSubResult(getSubInstance("PipelineReg1")->getEventResult("CK"), "PipelineReg1", number_bits_per_flit); 165 166 // Add crossbar traversal event 167 for(unsigned int i = 1; i <= number_output_ports; ++i) 168 { 169 Result* traverse_crossbar_event = getEventResult("TraverseCrossbar->Multicast" + (String)i); 170 traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("DFFD"), "Crossbar_Sel_DFF", number_crossbar_selects); 171 traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("DFFQ"), "Crossbar_Sel_DFF", number_crossbar_selects); 172 traverse_crossbar_event->addSubResult(getSubInstance("Crossbar_Sel_DFF")->getEventResult("CK"), "Crossbar_Sel_DFF", number_crossbar_selects); 173 traverse_crossbar_event->addSubResult(getSubInstance("Crossbar")->getEventResult("Multicast" + (String)i), "Crossbar", 1.0); 174 for(unsigned int j = 0; j < i; ++j) 175 { 176 traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("DFFD"), "PipelineReg2_" + (String)j, number_bits_per_flit); 177 traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("DFFQ"), "PipelineReg2_" + (String)j, number_bits_per_flit); 178 traverse_crossbar_event->addSubResult(getSubInstance("PipelineReg2_" + (String)j)->getEventResult("CK"), "PipelineReg2_" + (String)j, number_bits_per_flit); 179 } 180 } 181 182 // Add stage1 allocator arbitrate 183 Result* arb_sw_stage1_event = getEventResult("ArbitrateSwitch->ArbitrateStage1"); 184 arb_sw_stage1_event->addSubResult(getSubInstance("SwitchAllocator")->getEventResult("ArbitrateStage1"), "SwitchAllocator", 1.0); 185 186 // Add stage2 allocator arbitrate 187 Result* arb_sw_stage2_event = getEventResult("ArbitrateSwitch->ArbitrateStage2"); 188 arb_sw_stage2_event->addSubResult(getSubInstance("SwitchAllocator")->getEventResult("ArbitrateStage2"), "SwitchAllocator", 1.0); 189 190 // Add CK event 191 getEventResult("DistributeClock")->addSubResult(getSubInstance("ClockTree")->getEventResult("Send"), "ClockTree", 1.0); 192 return; 193 } 194 195 void Router::updateModel() 196 { 197 // Get parameters 198 unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt(); 199 200 // Update other components 201 getSubInstance("PipelineReg0")->update(); 202 getSubInstance("InputPort")->update(); 203 getSubInstance("PipelineReg1")->update(); 204 getSubInstance("Crossbar_Sel_DFF")->update(); 205 getSubInstance("Crossbar")->update(); 206 for(unsigned int i = 0; i < number_output_ports; ++i) 207 { 208 getSubInstance("PipelineReg2_" + (String)i)->update(); 209 } 210 getSubInstance("SwitchAllocator")->update(); 211 212 // Update clock tree 213 double total_clock_tree_cap = getNet("CK")->getTotalDownstreamCap(); 214 double router_area = getAreaResult("Active")->calculateSum(); 215 Model* clock_tree = getSubInstance("ClockTree"); 216 clock_tree->setProperty("SitePitch", sqrt(router_area)); 217 clock_tree->setProperty("TotalLoadCapPerBit", total_clock_tree_cap); 218 clock_tree->update(); 219 220 return; 221 } 222 223 void Router::propagateTransitionInfo() 224 { 225 // Update probability 226 unsigned int number_output_ports = getParameter("NumberOutputPorts"); 227 228 // Current event 229 const String& current_event = getGenProperties()->get("UseModelEvent"); 230 231 ElectricalModel* pipeline_reg0 = (ElectricalModel*)getSubInstance("PipelineReg0"); 232 propagatePortTransitionInfo(pipeline_reg0, "D", "FlitIn0"); 233 propagatePortTransitionInfo(pipeline_reg0, "CK", "CK"); 234 pipeline_reg0->use(); 235 236 ElectricalModel* input_port = (ElectricalModel*)getSubInstance("InputPort"); 237 propagatePortTransitionInfo(input_port, "FlitIn", pipeline_reg0, "Q"); 238 propagatePortTransitionInfo(input_port, "CK", "CK"); 239 input_port->getGenProperties()->set("UseModelEvent", "ReadWrite"); 240 input_port->use(); 241 242 ElectricalModel* pipeline_reg1 = (ElectricalModel*)getSubInstance("PipelineReg1"); 243 propagatePortTransitionInfo(pipeline_reg1, "D", "FlitIn0"); 244 propagatePortTransitionInfo(pipeline_reg1, "CK", "CK"); 245 pipeline_reg1->use(); 246 247 ElectricalModel* crossbar_sel_dff = (ElectricalModel*)getSubInstance("Crossbar_Sel_DFF"); 248 assignPortTransitionInfo(crossbar_sel_dff, "D", TransitionInfo()); 249 propagatePortTransitionInfo(crossbar_sel_dff, "CK", "CK"); 250 crossbar_sel_dff->use(); 251 252 ElectricalModel* crossbar = (ElectricalModel*)getSubInstance("Crossbar"); 253 bool is_crossbar_event = false; 254 for(unsigned int i = 1; i <= number_output_ports; ++i) 255 { 256 if(current_event == ("TraverseCrossbar->Multicast" + (String)i)) 257 { 258 is_crossbar_event = true; 259 // Assume the flit is sent from port 0 to port 0~i-1 260 // Apply default transition info 261 crossbar->applyTransitionInfo("Multicast" + (String)i); 262 // Overwrite transition info 263 propagatePortTransitionInfo(crossbar, "In0", "FlitIn0"); 264 break; 265 } 266 } 267 if(is_crossbar_event == false) 268 { 269 crossbar->applyTransitionInfo("Multicast1"); 270 propagatePortTransitionInfo(crossbar, "In0", "FlitIn0"); 271 } 272 crossbar->use(); 273 274 vector<ElectricalModel*> pipeline_reg2s(number_output_ports, NULL); 275 for(unsigned int i = 0; i < number_output_ports; ++i) 276 { 277 pipeline_reg2s[i] = (ElectricalModel*)getSubInstance("PipelineReg2_" + (String)i); 278 propagatePortTransitionInfo(pipeline_reg2s[i], "D", "FlitIn0"); 279 propagatePortTransitionInfo(pipeline_reg2s[i], "CK", "CK"); 280 pipeline_reg2s[i]->use(); 281 } 282 283 ElectricalModel* sw_allocator = (ElectricalModel*)getSubInstance("SwitchAllocator"); 284 if(current_event == "ArbitrateSwitch->ArbitrateStage1") 285 { 286 sw_allocator->applyTransitionInfo("ArbitrateStage1"); 287 } 288 else if(current_event == "ArbitrateSwitch->ArbitrateStage2") 289 { 290 sw_allocator->applyTransitionInfo("ArbitrateStage2"); 291 } 292 else 293 { 294 sw_allocator->applyTransitionInfo("Idle"); 295 } 296 sw_allocator->use(); 297 298 ElectricalModel* clock_tree = (ElectricalModel*)getSubInstance("ClockTree"); 299 propagatePortTransitionInfo(clock_tree, "In", "CK"); 300 clock_tree->use(); 301 return; 302 } 303 304 void Router::createRouterInputPort() 305 { 306 // Get parameters 307 unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt(); 308 unsigned int number_vns = getParameter("NumberVirtualNetworks").toUInt(); 309 const String& number_vcs_per_vn = getParameter("NumberVirtualChannelsPerVirtualNetwork"); 310 const String& number_bufs_per_vc = getParameter("NumberBuffersPerVirtualChannel"); 311 unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt(); 312 const String& buffer_model = getParameter("InputPort->BufferModel"); 313 314 // Init input port model 315 const String& input_port_name = "InputPort"; 316 RouterInputPort* input_port = new RouterInputPort(input_port_name, getTechModel()); 317 input_port->setParameter("NumberVirtualNetworks", number_vns); 318 input_port->setParameter("NumberVirtualChannelsPerVirtualNetwork", number_vcs_per_vn); 319 input_port->setParameter("NumberBuffersPerVirtualChannel", number_bufs_per_vc); 320 input_port->setParameter("NumberBitsPerFlit", number_bits_per_flit); 321 input_port->setParameter("BufferModel", buffer_model); 322 input_port->construct(); 323 324 unsigned int number_input_port_outputs = input_port->getGenProperties()->get("NumberOutputs"); 325 unsigned int number_input_port_addr_bits = input_port->getGenProperties()->get("NumberAddressBits"); 326 getGenProperties()->set("InputPort->NumberOutputs", number_input_port_outputs); 327 getGenProperties()->set("InputPort->NumberAddressBits", number_input_port_addr_bits); 328 329 unsigned int total_number_vcs = input_port->getGenProperties()->get("TotalNumberVirtualChannels"); 330 getGenProperties()->set("TotalNumberVirtualChannels", total_number_vcs); 331 332 // Add the instance and the results 333 addSubInstances(input_port, number_input_ports); 334 addElectricalSubResults(input_port, number_input_ports); 335 336 // Create connections 337 createNet("InputPort_In", makeNetIndex(0, number_bits_per_flit-1)); 338 createNet("InputPort_Out", makeNetIndex(0, number_bits_per_flit-1)); 339 340 assignVirtualFanout("InputPort_In", "PipelineReg0_Out"); 341 portConnect(input_port, "FlitIn", "InputPort_In"); 342 portConnect(input_port, "CK", "CK"); 343 portConnect(input_port, "FlitOut", "InputPort_Out"); 344 assignVirtualFanin("PipelineReg1_In", "InputPort_Out"); 345 346 return; 347 } 348 349 void Router::createVirtualChannelAllocator() 350 {} 351 352 void Router::createSwitchAllocator() 353 { 354 // Get parameters 355 unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt(); 356 unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt(); 357 unsigned int total_number_vcs = getGenProperties()->get("TotalNumberVirtualChannels").toUInt(); 358 const String& arb_model = getParameter("SwitchAllocator->ArbiterModel"); 359 360 // Init switch allocator model 361 const String& sw_allocator_name = "SwitchAllocator"; 362 RouterSwitchAllocator* sw_allocator = new RouterSwitchAllocator(sw_allocator_name, getTechModel()); 363 sw_allocator->setParameter("NumberInputPorts", number_input_ports); 364 sw_allocator->setParameter("NumberOutputPorts", number_output_ports); 365 sw_allocator->setParameter("TotalNumberVirtualChannels", total_number_vcs); 366 sw_allocator->setParameter("ArbiterModel", arb_model); 367 sw_allocator->construct(); 368 369 // Add the instance and the results 370 addSubInstances(sw_allocator, 1.0); 371 addElectricalSubResults(sw_allocator, 1.0); 372 373 // Create connections (currently connect CK only) 374 portConnect(sw_allocator, "CK", "CK"); 375 return; 376 } 377 378 void Router::createCrossbar() 379 { 380 // Get parameters 381 const String& crossbar_model = getParameter("CrossbarModel"); 382 unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt(); 383 unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt(); 384 unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt(); 385 unsigned int number_input_port_outputs = getGenProperties()->get("InputPort->NumberOutputs").toUInt(); 386 387 unsigned int number_crossbar_inputs = number_input_port_outputs * number_input_ports; 388 unsigned int number_crossbar_outputs = number_output_ports; 389 getGenProperties()->set("Crossbar->NumberInputs", number_crossbar_inputs); 390 getGenProperties()->set("Crossbar->NumberOutputs", number_crossbar_outputs); 391 392 // Init crossbar model 393 const String& crossbar_name = "Crossbar"; 394 ElectricalModel* crossbar = ModelGen::createCrossbar(crossbar_model, crossbar_name, getTechModel()); 395 crossbar->setParameter("NumberInputs", number_crossbar_inputs); 396 crossbar->setParameter("NumberOutputs", number_crossbar_outputs); 397 crossbar->setParameter("NumberBits", number_bits_per_flit); 398 crossbar->setParameter("BitDuplicate", "TRUE"); 399 crossbar->construct(); 400 401 unsigned int number_crossbar_selects = crossbar->getGenProperties()->get("NumberSelectsPerPort"); 402 getGenProperties()->set("Crossbar->NumberSelects", number_crossbar_selects); 403 404 // Init DFF for crossbar selections 405 const String& crossbar_sel_dff_name = "Crossbar_Sel_DFF"; 406 StdCell* crossbar_sel_dff = getTechModel()->getStdCellLib()->createStdCell("DFFQ", crossbar_sel_dff_name); 407 crossbar_sel_dff->construct(); 408 409 // Add instances and results 410 addSubInstances(crossbar, 1.0); 411 addElectricalSubResults(crossbar, 1.0); 412 413 addSubInstances(crossbar_sel_dff, number_crossbar_outputs * number_crossbar_selects); 414 addElectricalSubResults(crossbar_sel_dff, number_crossbar_outputs * number_crossbar_selects); 415 416 // Create connections 417 createNet("Crossbar_Sel_DFF_Out"); 418 for(unsigned int i = 0; i < number_crossbar_outputs; ++i) 419 { 420 for(unsigned int j = 0; j < number_crossbar_selects; ++j) 421 { 422 createNet(String::format("Crossbar_Sel%d_%d", i, j)); 423 } 424 createNet("Crossbar_Out" + (String)i, makeNetIndex(0, number_bits_per_flit-1)); 425 } 426 for(unsigned int i = 0; i < number_crossbar_inputs; ++i) 427 { 428 createNet("Crossbar_In" + (String)i, makeNetIndex(0, number_bits_per_flit-1)); 429 } 430 431 for(unsigned int i = 0; i < number_crossbar_selects; ++i) 432 { 433 portConnect(crossbar_sel_dff, "CK", "CK"); 434 } 435 portConnect(crossbar_sel_dff, "Q", "Crossbar_Sel_DFF_Out"); 436 for(unsigned int i = 0; i < number_crossbar_inputs; ++i) 437 { 438 assignVirtualFanout("Crossbar_In" + (String)i, "PipelineReg1_Out"); 439 portConnect(crossbar, "In" + (String)i, "Crossbar_In" + (String)i); 440 } 441 for(unsigned int i = 0; i < number_crossbar_outputs; ++i) 442 { 443 for(unsigned int j = 0; j < number_crossbar_selects; ++j) 444 { 445 assignVirtualFanout(String::format("Crossbar_Sel%d_%d", i, j), "Crossbar_Sel_DFF_Out"); 446 portConnect(crossbar, String::format("Sel%d_%d", i, j), String::format("Crossbar_Sel%d_%d", i, j)); 447 } 448 portConnect(crossbar, "Out" + (String)i, "Crossbar_Out" + (String)i); 449 assignVirtualFanin("PipelineReg2_In" + (String)i, "Crossbar_Out" + (String)i); 450 } 451 452 return; 453 } 454 455 void Router::createPipelineReg() 456 { 457 // Get parameters 458 unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt(); 459 unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt(); 460 unsigned int number_bits_per_flit = getParameter("NumberBitsPerFlit").toUInt(); 461 unsigned int number_crossbar_inputs = getGenProperties()->get("Crossbar->NumberInputs"); 462 463 // Init pipeline reg model 464 // First stage: from router input to input port 465 const String& pipeline_reg0_name = "PipelineReg0"; 466 StdCell* pipeline_reg0 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg0_name); 467 pipeline_reg0->construct(); 468 // Second stage: from input port to crossbar 469 const String& pipeline_reg1_name = "PipelineReg1"; 470 StdCell* pipeline_reg1 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg1_name); 471 pipeline_reg1->construct(); 472 473 // Third stage: from crossbar to router output 474 vector<StdCell*> pipeline_reg2s(number_output_ports, (StdCell*)NULL); 475 vector<String> pipeline_reg2_names(number_output_ports, ""); 476 for(unsigned int i = 0; i < number_output_ports; ++i) 477 { 478 pipeline_reg2_names[i] = "PipelineReg2_" + (String)i; 479 pipeline_reg2s[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", pipeline_reg2_names[i]); 480 pipeline_reg2s[i]->construct(); 481 } 482 483 // Add instances and results 484 addSubInstances(pipeline_reg0, number_input_ports * number_bits_per_flit); 485 addElectricalSubResults(pipeline_reg0, number_input_ports * number_bits_per_flit); 486 487 addSubInstances(pipeline_reg1, number_crossbar_inputs * number_bits_per_flit); 488 addElectricalSubResults(pipeline_reg1, number_crossbar_inputs * number_bits_per_flit); 489 490 for(unsigned int i = 0; i < number_output_ports; ++i) 491 { 492 addSubInstances(pipeline_reg2s[i], number_bits_per_flit); 493 addElectricalSubResults(pipeline_reg2s[i], number_bits_per_flit); 494 } 495 496 // Create data connections 497 for(unsigned int i = 0; i < number_input_ports; ++i) 498 { 499 assignVirtualFanin("PipelineReg0_In", "FlitIn" + (String)i); 500 } 501 portConnect(pipeline_reg0, "D", "PipelineReg0_In"); 502 portConnect(pipeline_reg0, "Q", "PipelineReg0_Out"); 503 portConnect(pipeline_reg1, "D", "PipelineReg1_In"); 504 portConnect(pipeline_reg1, "Q", "PipelineReg1_Out"); 505 for(unsigned int i = 0; i < number_output_ports; ++i) 506 { 507 portConnect(pipeline_reg2s[i], "D", "PipelineReg2_In" + (String)i); 508 portConnect(pipeline_reg2s[i], "Q", "PipelineReg2_Out" + (String)i); 509 assignVirtualFanout("FlitOut" + (String)i, "PipelineReg2_Out" + (String)i); 510 } 511 512 // Create CK connections 513 for(unsigned int n = 0; n < number_bits_per_flit; ++n) 514 { 515 for(unsigned int i = 0; i < number_input_ports; ++i) 516 { 517 portConnect(pipeline_reg0, "CK", "CK"); 518 } 519 for(unsigned int i = 0; i < number_crossbar_inputs; ++i) 520 { 521 portConnect(pipeline_reg1, "CK", "CK"); 522 } 523 for(unsigned int i = 0; i < number_output_ports; ++i) 524 { 525 portConnect(pipeline_reg2s[i], "CK", "CK"); 526 } 527 } 528 return; 529 } 530 531 void Router::createClockTree() 532 { 533 // Get parameters 534 const String& clock_tree_model = getParameter("ClockTreeModel"); 535 const String& clock_tree_number_levels = getParameter("ClockTree->NumberLevels"); 536 const String& clock_tree_wire_layer = getParameter("ClockTree->WireLayer"); 537 const String& clock_tree_wire_width_multiplier = getParameter("ClockTree->WireWidthMultiplier"); 538 const String& clock_tree_wire_spacing_multiplier = getParameter("ClockTree->WireSpacingMultiplier"); 539 540 // Init clock tree model 541 const String& clock_tree_name = "ClockTree"; 542 ElectricalModel* clock_tree = (ElectricalModel*)ModelGen::createModel(clock_tree_model, clock_tree_name, getTechModel()); 543 clock_tree->setParameter("NumberLevels", clock_tree_number_levels); 544 clock_tree->setParameter("NumberBits", 1); 545 clock_tree->setParameter("WireLayer", clock_tree_wire_layer); 546 clock_tree->setParameter("WireWidthMultiplier", clock_tree_wire_width_multiplier); 547 clock_tree->setParameter("WireSpacingMultiplier", clock_tree_wire_spacing_multiplier); 548 clock_tree->construct(); 549 550 // Add instances and results 551 addSubInstances(clock_tree, 1.0); 552 addElectricalSubResults(clock_tree, 1.0); 553 554 return; 555 } 556} // namespace DSENT 557 558