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