BroadcastHTree.cc revision 10447
1#include "model/electrical/BroadcastHTree.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/std_cells/StdCellLib.h" 10#include "model/std_cells/StdCell.h" 11#include "model/timing_graph/ElectricalLoad.h" 12#include "model/timing_graph/ElectricalDelay.h" 13#include "model/timing_graph/ElectricalDriver.h" 14#include "model/timing_graph/ElectricalTimingTree.h" 15#include "model/timing_graph/ElectricalNet.h" 16 17namespace DSENT 18{ 19 using std::pow; 20 using std::vector; 21 22 BroadcastHTree::BroadcastHTree(const String& instance_name_, const TechModel* tech_model_) 23 : ElectricalModel(instance_name_, tech_model_) 24 { 25 initParameters(); 26 initProperties(); 27 28 m_leaf_load_ = NULL; 29 m_leaf_head_driver_ = NULL; 30 m_leaf_head_load_ = NULL; 31 } 32 33 BroadcastHTree::~BroadcastHTree() 34 { 35 clearPtrVector<StdCell>(&m_repeaters_); 36 clearPtrVector<ElectricalLoad>(&m_repeater_loads_); 37 clearPtrVector<ElectricalTimingTree>(&m_timing_trees_); 38 clearPtrVector<StdCell>(&m_leaf_drivers_); 39 delete m_leaf_load_; 40 delete m_leaf_head_driver_; 41 delete m_leaf_head_load_; 42 } 43 44 void BroadcastHTree::initParameters() 45 { 46 addParameterName("NumberLevels"); 47 addParameterName("NumberBits"); 48 addParameterName("WireLayer"); 49 addParameterName("WireWidthMultiplier", 1.0); 50 addParameterName("WireSpacingMultiplier", 1.0); 51 return; 52 } 53 54 void BroadcastHTree::initProperties() 55 { 56 addPropertyName("SitePitch"); 57 addPropertyName("TotalLoadCapPerBit"); 58 return; 59 } 60 61 BroadcastHTree* BroadcastHTree::clone() const 62 { 63 // TODO 64 return NULL; 65 } 66 67 void BroadcastHTree::constructModel() 68 { 69 // Get parameters 70 unsigned int number_levels = getParameter("NumberLevels").toUInt(); 71 unsigned int number_bits = getParameter("NumberBits").toUInt(); 72 const String& wire_layer = getParameter("WireLayer"); 73 double wire_width_multiplier = getParameter("WireWidthMultiplier").toDouble(); 74 double wire_spacing_multiplier = getParameter("WireSpacingMultiplier").toDouble(); 75 76 ASSERT(number_levels > 0, "[Error] " + getInstanceName() + 77 " -> Number of levels must be > 0!"); 78 ASSERT(number_bits > 0, "[Error] " + getInstanceName() + 79 " -> Number of bits must be > 0!"); 80 ASSERT(getTechModel()->isWireLayerExist(wire_layer), "[Error] " + getInstanceName() + 81 " -> Wire layer does not exist!"); 82 ASSERT(wire_width_multiplier >= 1.0, "[Error] " + getInstanceName() + 83 " -> Wire width multiplier must be >= 1.0!"); 84 ASSERT(wire_spacing_multiplier >= 1.0, "[Error] " + getInstanceName() + 85 " -> Wire spacing multiplier must be >= 1.0!"); 86 87 double wire_min_width = getTechModel()->get("Wire->" + wire_layer + "->MinWidth").toDouble(); 88 double wire_min_spacing = getTechModel()->get("Wire->" + wire_layer + "->MinSpacing").toDouble(); 89 90 double wire_width = wire_min_width * wire_width_multiplier; 91 double wire_spacing = wire_min_spacing * wire_spacing_multiplier; 92 93 double wire_cap_per_len = getTechModel()->calculateWireCapacitance(wire_layer, wire_width, wire_spacing, 1.0); 94 double wire_res_per_len = getTechModel()->calculateWireResistance(wire_layer, wire_width, 1.0); 95 96 getGenProperties()->set("WireWidth", wire_width); 97 getGenProperties()->set("WireSpacing", wire_spacing); 98 getGenProperties()->set("WireCapacitancePerLength", wire_cap_per_len); 99 getGenProperties()->set("WireResistancePerLength", wire_res_per_len); 100 101 // Create ports 102 createInputPort("In", makeNetIndex(0, number_bits-1)); 103 createOutputPort("Out", makeNetIndex(0, number_bits-1)); 104 105 // Create connections 106 createNet("InTmp"); 107 createNet("OutTmp"); 108 assignVirtualFanin("InTmp", "In"); 109 assignVirtualFanout("Out", "OutTmp"); 110 111 createLoad("In_Cap"); 112 createDelay("In_to_Out_delay"); 113 114 ElectricalLoad* in_cap = getLoad("In_Cap"); 115 ElectricalDelay* in_to_out_delay = getDelay("In_to_Out_delay"); 116 117 getNet("InTmp")->addDownstreamNode(in_cap); 118 in_cap->addDownstreamNode(in_to_out_delay); 119 120 // Init 121 for(unsigned int i = 0; i < number_levels; ++i) 122 { 123 StdCell* repeater = getTechModel()->getStdCellLib()->createStdCell("INV", "Repeater" + (String)i); 124 ElectricalLoad* repeater_load = new ElectricalLoad("RepeaterIn_Cap" + (String)i, this); 125 ElectricalTimingTree* timing_tree = new ElectricalTimingTree("RepeatedLink" + (String)i, this); 126 127 repeater->construct(); 128 repeater->getNet("Y")->addDownstreamNode(repeater_load); 129 m_repeaters_.push_back(repeater); 130 m_repeater_loads_.push_back(repeater_load); 131 m_timing_trees_.push_back(timing_tree); 132 } 133 134 // Create area, power, and event results 135 createElectricalAtomicResults(); 136 createElectricalEventResult("Send"); 137 addEventResult(new AtomicResult("DriveLoad")); 138 addEventResult(new AtomicResult("DriveTree")); 139 140 getEventResult("Send")->addSubResult(getEventResult("DriveLoad"), "Self", 1.0); 141 getEventResult("Send")->addSubResult(getEventResult("DriveTree"), "Self", 1.0); 142 return; 143 } 144 145 void BroadcastHTree::updateModel() 146 { 147 // Get properties 148 double site_pitch = getProperty("SitePitch").toDouble(); 149 double total_load_cap_per_bit = getProperty("TotalLoadCapPerBit").toDouble(); 150 151 ASSERT(site_pitch > 0, "[Error] " + getInstanceName() + 152 " -> Site pitch must be > 0!"); 153 ASSERT(total_load_cap_per_bit >= 0.0, "[Error] " + getInstanceName() + 154 " -> Total load capacitance per bit must be >= 0!"); 155 156 // Get parameters 157 unsigned int number_levels = getParameter("NumberLevels"); 158 unsigned int number_bits = getParameter("NumberBits"); 159 160 const String& wire_layer = getParameter("WireLayer"); 161 double wire_width = getGenProperties()->get("WireWidth").toDouble(); 162 double wire_spacing = getGenProperties()->get("WireSpacing").toDouble(); 163 double wire_cap_per_len = getGenProperties()->get("WireCapacitancePerLength").toDouble(); 164 double wire_res_per_len = getGenProperties()->get("WireResistancePerLength").toDouble(); 165 166 double leaf_load_cap = total_load_cap_per_bit / pow(2.0, (double)(number_levels-1)); 167 168 vector<double> wire_caps(number_levels, 0.0); 169 vector<double> wire_ress(number_levels, 0.0); 170 double wire_length = site_pitch / 2.0; 171 for(unsigned int i = 0; i < number_levels; ++i) 172 { 173 wire_caps[i] = wire_cap_per_len * wire_length; 174 wire_ress[i] = wire_res_per_len * wire_length; 175 wire_length /= 2.0; 176 } 177 178 // Start sizing each stage of repeaters for a transition times. TODO: Find a heuristic about 179 // how the transition time is done...place and route tools make this user-specified 180 double required_transition = 40e-12; 181 m_number_segments_.resize(number_levels, 1); 182 for(unsigned int i = 0; i < number_levels; ++i) 183 { 184 Log::printLine(getInstanceName() + " -> Beginning Repeater Insertion " + (String)i); 185 186 double transition; 187 unsigned int iteration = 0; 188 m_repeaters_[i]->setMinDrivingStrength(); 189 m_repeaters_[i]->getNet("Y")->setDistributedCap(wire_caps[i] / m_number_segments_[i]); 190 m_repeaters_[i]->getNet("Y")->setDistributedRes(wire_ress[i] / m_number_segments_[i]); 191 m_repeater_loads_[i]->setLoadCap(m_repeaters_[i]->getNet("A")->getTotalDownstreamCap()); 192 193 transition = m_timing_trees_[i]->calculateNodeTransition(m_repeaters_[i]->getNet("Y")); 194 195 while(required_transition < transition) 196 { 197 Log::printLine(getInstanceName() + " -> Repeater Insertion Iteration " + (String)iteration + 198 ": Required transition = " + (String)required_transition + 199 ", Transition = " + (String)transition + 200 ", Slack = " + (String)(required_transition - transition) + 201 ", Number of repeaters = " + (String)m_number_segments_[i]); 202 203 // Size up if transition is not met 204 while(required_transition < transition) 205 { 206 if(m_repeaters_[i]->hasMaxDrivingStrength()) 207 { 208 break; 209 } 210 m_repeaters_[i]->increaseDrivingStrength(); 211 m_repeater_loads_[i]->setLoadCap(m_repeaters_[i]->getNet("A")->getTotalDownstreamCap()); 212 transition = m_timing_trees_[i]->calculateNodeTransition(m_repeaters_[i]->getNet("Y")); 213 214 iteration++; 215 Log::printLine(getInstanceName() + " -> Slack: " + (String)(required_transition - transition)); 216 } 217 // Increase number of segments if thansition is not met 218 if(required_transition < transition) 219 { 220 m_number_segments_[i]++; 221 m_repeaters_[i]->setMinDrivingStrength(); 222 m_repeaters_[i]->getNet("Y")->setDistributedCap(wire_caps[i] / m_number_segments_[i]); 223 m_repeaters_[i]->getNet("Y")->setDistributedRes(wire_ress[i] / m_number_segments_[i]); 224 m_repeater_loads_[i]->setLoadCap(m_repeaters_[i]->getNet("A")->getTotalDownstreamCap()); 225 transition = m_timing_trees_[i]->calculateNodeTransition(m_repeaters_[i]->getNet("Y")); 226 } 227 } 228 Log::printLine(getInstanceName() + " -> Repeater Insertion " + (String)i + " Ended after Iteration: " + (String)iteration + 229 ": Required transition = " + (String)required_transition + 230 ", Transition = " + (String)transition + 231 ", Slack = " + (String)(required_transition - transition) + 232 ", Number of repeaters = " + (String)m_number_segments_[i]); 233 } 234 235 // Insert inverters to ensure the transition time at the leaf 236 int min_driving_strength_idx = m_repeaters_[number_levels-1]->getDrivingStrengthIdx(); 237 238 // Remove everything and rebuild again 239 clearPtrVector<StdCell>(&m_leaf_drivers_); 240 delete m_leaf_load_; 241 delete m_leaf_head_driver_; 242 delete m_leaf_head_load_; 243 244 m_leaf_head_driver_ = getTechModel()->getStdCellLib()->createStdCell("INV", "LeafHeadDriver"); 245 m_leaf_head_driver_->construct(); 246 m_leaf_head_driver_->setDrivingStrengthIdx(min_driving_strength_idx); 247 248 m_leaf_head_load_ = new ElectricalLoad("LeafHead_Cap", this); 249 m_leaf_head_driver_->getNet("Y")->addDownstreamNode(m_leaf_head_load_); 250 251 m_leaf_load_ = new ElectricalLoad("Leaf_Cap", this); 252 m_leaf_load_->setLoadCap(leaf_load_cap); 253 254 StdCell* inv = getTechModel()->getStdCellLib()->createStdCell("INV", "LeafDriver0"); 255 inv->construct(); 256 inv->getNet("Y")->addDownstreamNode(m_leaf_load_); 257 inv->setDrivingStrengthIdx(min_driving_strength_idx); 258 m_leaf_drivers_.push_back(inv); 259 260 m_leaf_head_load_->setLoadCap(m_leaf_drivers_[0]->getNet("A")->getTotalDownstreamCap()); 261 262 // Start inserting the buffers 263 ElectricalTimingTree t2("LeafHead", m_leaf_head_driver_); 264 int curr_driver = 0; 265 unsigned int iteration = 0; 266 while(true) 267 { 268 ElectricalTimingTree t("LeafDriver", m_leaf_drivers_[curr_driver]); 269 double transition = t.calculateNodeTransition(m_leaf_drivers_[curr_driver]->getNet("Y")); 270 Log::printLine(getInstanceName() + " -> Buffer Insertion : " + (String)iteration + 271 ": Required transition = " + (String)required_transition + 272 ", Transition = " + (String)transition + 273 ", Slack = " + (String)(required_transition - transition) + 274 ", Number of buffers = " + (String)(curr_driver+1)); 275 276 // Size up the inverter at curr_driver so that it could drive the next stage 277 while(required_transition < transition) 278 { 279 if(m_leaf_drivers_[curr_driver]->hasMaxDrivingStrength()) 280 { 281 const String& warning_msg = "[Warning] " + getInstanceName() + " -> Transition not met" + 282 ": Required transition = " + (String)required_transition + 283 ", Transition = " + (String)transition + 284 ", Slack = " + (String)(required_transition - transition); 285 Log::printLine(std::cerr, warning_msg); 286 break; 287 } 288 m_leaf_drivers_[curr_driver]->increaseDrivingStrength(); 289 transition = t.calculateNodeTransition(m_leaf_drivers_[curr_driver]->getNet("Y")); 290 iteration++; 291 } 292 // Add an additional inverter if the transition for the first stage does not meet the required transition 293 m_leaf_head_load_->setLoadCap(m_leaf_drivers_[curr_driver]->getNet("A")->getTotalDownstreamCap()); 294 transition = t2.calculateNodeTransition(m_leaf_head_driver_->getNet("Y")); 295 if(required_transition < transition) 296 { 297 inv = getTechModel()->getStdCellLib()->createStdCell("INV", "LeafDriver" + (String)(curr_driver+1)); 298 inv->construct(); 299 inv->getNet("Y")->addDownstreamNode(m_leaf_drivers_[curr_driver]->getNet("A")); 300 inv->setDrivingStrengthIdx(min_driving_strength_idx); 301 m_leaf_drivers_.push_back(inv); 302 curr_driver++; 303 } 304 else 305 { 306 Log::printLine(getInstanceName() + " -> Buffer Insertion Ended after Iteration: " + (String)iteration + 307 ", Number of buffers = " + (String)(curr_driver+1)); 308 break; 309 } 310 } 311 312 313 // Update electrical interfaces 314 getLoad("In_Cap")->setLoadCap(m_repeaters_[0]->getNet("A")->getTotalDownstreamCap()); 315 // TODO 316 getDelay("In_to_Out_delay")->setDelay(0.0); 317 318 // Reset all the atomic results to 0 before start updating new results 319 resetElectricalAtomicResults(); 320 321 // Update area, power results 322 double wire_area = 0.0; 323 wire_length = site_pitch / 2.0; 324 unsigned int number_branches = 1; 325 for(unsigned int i = 0; i < number_levels; ++i) 326 { 327 wire_area += wire_length * (wire_width + wire_spacing) * number_branches * number_bits; 328 addElecticalAtomicResultValues(m_repeaters_[i], m_number_segments_[i] * number_branches * number_bits); 329 wire_length /= 2.0; 330 number_branches *= 2; 331 } 332 number_branches = (unsigned int)pow(2.0, (double)number_levels-1); 333 addElecticalAtomicResultValues(m_leaf_head_driver_, number_branches * number_bits); 334 for(unsigned int i = 0; i < m_leaf_drivers_.size(); ++i) 335 { 336 addElecticalAtomicResultValues(m_leaf_drivers_[i], number_branches * number_bits); 337 } 338 addElecticalWireAtomicResultValue(wire_layer, wire_area); 339 340 return; 341 } 342 343 void BroadcastHTree::useModel() 344 { 345 unsigned int number_bits = getParameter("NumberBits").toUInt(); 346 unsigned int number_levels = getParameter("NumberLevels").toUInt(); 347 348 // Update the transition information for the modeled repeaters 349 // Since we only modeled one repeater. So the transition information for 0->0 and 1->1 350 // is averaged out 351 const TransitionInfo& trans_In = getInputPort("In")->getTransitionInfo(); 352 double average_static_transition = (trans_In.getNumberTransitions00() + trans_In.getNumberTransitions11()) / 2.0; 353 TransitionInfo mod_trans_In(average_static_transition, trans_In.getNumberTransitions01(), average_static_transition); 354 355 // Propagate the transition information 356 propagateTransitionInfo(); 357 358 // Update leakage and event 359 double energy = 0.0; 360 double power = 0.0; 361 unsigned int number_branches = 1; 362 for(unsigned int i = 0; i < number_levels; ++i) 363 { 364 assignPortTransitionInfo(m_repeaters_[i], "A", mod_trans_In); 365 m_repeaters_[i]->use(); 366 power += m_repeaters_[i]->getNddPowerResult("Leakage")->calculateSum() * m_number_segments_[i] * number_branches; 367 energy += m_repeaters_[i]->getEventResult("INV")->calculateSum() * m_number_segments_[i] * number_branches; 368 number_branches *= 2; 369 } 370 energy *= number_bits; 371 getEventResult("DriveTree")->setValue(energy); 372 373 energy = 0.0; 374 assignPortTransitionInfo(m_leaf_head_driver_, "A", mod_trans_In); 375 m_leaf_head_driver_->use(); 376 number_branches = (unsigned int)pow(2.0, (double)number_levels-1); 377 power += m_leaf_head_driver_->getNddPowerResult("Leakage")->calculateSum() * number_branches; 378 energy += m_leaf_head_driver_->getEventResult("INV")->calculateSum() * number_branches; 379 for(unsigned int i = 0; i < m_leaf_drivers_.size(); ++i) 380 { 381 assignPortTransitionInfo(m_leaf_drivers_[i], "A", mod_trans_In); 382 m_leaf_drivers_[i]->use(); 383 power += m_leaf_drivers_[i]->getNddPowerResult("Leakage")->calculateSum() * number_branches; 384 energy += m_leaf_drivers_[i]->getEventResult("INV")->calculateSum() * number_branches; 385 } 386 power *= number_bits; 387 energy *= number_bits; 388 getEventResult("DriveLoad")->setValue(energy); 389 getNddPowerResult("Leakage")->setValue(power); 390 391 return; 392 } 393 394 void BroadcastHTree::propagateTransitionInfo() 395 { 396 propagatePortTransitionInfo("Out", "In"); 397 return; 398 } 399} // namespace DSENT 400 401