RepeatedLink.cc revision 10447
1#include "model/electrical/RepeatedLink.h" 2 3#include "model/PortInfo.h" 4#include "model/EventInfo.h" 5#include "model/TransitionInfo.h" 6#include "model/std_cells/StdCellLib.h" 7#include "model/std_cells/StdCell.h" 8#include "model/timing_graph/ElectricalTimingTree.h" 9#include "model/timing_graph/ElectricalTimingNode.h" 10#include "model/timing_graph/ElectricalNet.h" 11#include "model/timing_graph/ElectricalDriver.h" 12#include "model/timing_graph/ElectricalDelay.h" 13#include "model/timing_graph/ElectricalLoad.h" 14 15namespace DSENT 16{ 17 RepeatedLink::RepeatedLink(const String& instance_name_, const TechModel* tech_model_) 18 : ElectricalModel(instance_name_, tech_model_) 19 { 20 m_repeater_ = NULL; 21 m_repeater_load_ = NULL; 22 m_timing_tree_ = NULL; 23 24 initParameters(); 25 initProperties(); 26 } 27 28 RepeatedLink::~RepeatedLink() 29 { 30 delete m_repeater_; 31 delete m_repeater_load_; 32 delete m_timing_tree_; 33 } 34 35 void RepeatedLink::initParameters() 36 { 37 addParameterName("NumberBits"); 38 addParameterName("WireLayer"); 39 addParameterName("WireWidthMultiplier", 1.0); 40 addParameterName("WireSpacingMultiplier", 1.0); 41 return; 42 } 43 44 void RepeatedLink::initProperties() 45 { 46 addPropertyName("WireLength"); 47 addPropertyName("Delay"); 48 addPropertyName("IsKeepParity", "TRUE"); 49 return; 50 } 51 52 RepeatedLink* RepeatedLink::clone() const 53 { 54 // TODO 55 return NULL; 56 } 57 58 void RepeatedLink::constructModel() 59 { 60 // Get parameters 61 unsigned int number_bits = getParameter("NumberBits").toUInt(); 62 const String& wire_layer = getParameter("WireLayer"); 63 double wire_width_multiplier = getParameter("WireWidthMultiplier").toDouble(); 64 double wire_spacing_multiplier = getParameter("WireSpacingMultiplier").toDouble(); 65 66 ASSERT(number_bits > 0, "[Error] " + getInstanceName() + 67 " -> Number of bits must be > 0!"); 68 ASSERT(getTechModel()->isWireLayerExist(wire_layer), "[Error] " + getInstanceName() + 69 " -> Wire layer does not exist!"); 70 ASSERT(wire_width_multiplier >= 1.0, "[Error] " + getInstanceName() + 71 " -> Wire width multiplier must be >= 1.0!"); 72 ASSERT(wire_spacing_multiplier >= 1.0, "[Error] " + getInstanceName() + 73 " -> Wire spacing multiplier must be >= 1.0!"); 74 75 double wire_min_width = getTechModel()->get("Wire->" + wire_layer + "->MinWidth").toDouble(); 76 double wire_min_spacing = getTechModel()->get("Wire->" + wire_layer + "->MinSpacing").toDouble(); 77 78 double wire_width = wire_min_width * wire_width_multiplier; 79 double wire_spacing = wire_min_spacing * wire_spacing_multiplier; 80 81 double wire_cap_per_len = getTechModel()->calculateWireCapacitance(wire_layer, wire_width, wire_spacing, 1.0); 82 double wire_res_per_len = getTechModel()->calculateWireResistance(wire_layer, wire_width, 1.0); 83 84 getGenProperties()->set("WireWidth", wire_width); 85 getGenProperties()->set("WireSpacing", wire_spacing); 86 getGenProperties()->set("WireCapacitancePerLength", wire_cap_per_len); 87 getGenProperties()->set("WireResistancePerLength", wire_res_per_len); 88 89 // Create ports 90 createInputPort("In", makeNetIndex(0, number_bits-1)); 91 createOutputPort("Out", makeNetIndex(0, number_bits-1)); 92 93 // Create area, power, and event results 94 createElectricalAtomicResults(); 95 createElectricalEventAtomicResult("Send"); 96 97 // Create connections 98 // Since the length is not set yet, we only to virtual fan-in and virtual fan-out 99 createNet("InTmp"); 100 createNet("OutTmp"); 101 assignVirtualFanin("InTmp", "In"); 102 assignVirtualFanout("Out", "OutTmp"); 103 104 // Build Electrical Connectivity 105 createLoad("In_Cap"); 106 createDelay("In_to_Out_delay"); 107 createDriver("Out_Ron", false); // Indicate this driver is not sizable 108 109 ElectricalLoad* in_cap = getLoad("In_Cap"); 110 ElectricalDelay* in_to_out_delay = getDelay("In_to_Out_delay"); 111 ElectricalDriver* out_ron = getDriver("Out_Ron"); 112 113 getNet("InTmp")->addDownstreamNode(in_cap); 114 in_cap->addDownstreamNode(in_to_out_delay); 115 in_to_out_delay->addDownstreamNode(out_ron); 116 out_ron->addDownstreamNode(getNet("OutTmp")); 117 118 // Init a repeater and a load to mimic a segment of a repeated link 119 m_repeater_ = getTechModel()->getStdCellLib()->createStdCell("INV", "Repeater"); 120 m_repeater_->construct(); 121 m_repeater_load_ = new ElectricalLoad("RepeaterIn_Cap", this); 122 // Make path repeater_ -> repeater_load_ 123 // to catch the repeater's input/output cap and ensure only one inverter delay 124 // is added 125 m_repeater_->getNet("Y")->addDownstreamNode(m_repeater_load_); 126 // Init a timing object to calculate delay 127 m_timing_tree_ = new ElectricalTimingTree("RepeatedLink", this); 128 m_timing_tree_->performCritPathExtract(m_repeater_->getNet("A")); 129 return; 130 } 131 132 void RepeatedLink::updateModel() 133 { 134 unsigned int number_bits = getParameter("NumberBits").toUInt(); 135 136 // Get properties 137 double wire_length = getProperty("WireLength").toDouble(); 138 double required_delay = getProperty("Delay").toDouble(); 139 bool isKeepParity = getProperty("IsKeepParity").toBool(); 140 141 ASSERT(wire_length >= 0, "[Error] " + getInstanceName() + 142 " -> Wire length must be >= 0!"); 143 ASSERT(required_delay >= 0, "[Error] " + getInstanceName() + 144 " -> Required delay must be >= 0!"); 145 146 const String& wire_layer = getParameter("WireLayer"); 147 double wire_width = getGenProperties()->get("WireWidth").toDouble(); 148 double wire_spacing = getGenProperties()->get("WireSpacing").toDouble(); 149 150 // Calculate the total wire cap and total wire res 151 double wire_cap_per_len = getGenProperties()->get("WireCapacitancePerLength").toDouble(); 152 double wire_res_per_len = getGenProperties()->get("WireResistancePerLength").toDouble(); 153 double total_wire_cap = wire_cap_per_len * wire_length; 154 double total_wire_res = wire_res_per_len * wire_length; 155 156 m_repeater_->update(); 157 158 unsigned int increment_segments = (isKeepParity)? 2:1; 159 unsigned int number_segments = increment_segments; 160 double delay; 161 m_repeater_->setMinDrivingStrength(); 162 m_repeater_->getNet("Y")->setDistributedCap(total_wire_cap / number_segments); 163 m_repeater_->getNet("Y")->setDistributedRes(total_wire_res / number_segments); 164 m_repeater_load_->setLoadCap(m_repeater_->getNet("A")->getTotalDownstreamCap()); 165 m_timing_tree_->performCritPathExtract(m_repeater_->getNet("A")); 166 delay = m_timing_tree_->calculateCritPathDelay(m_repeater_->getNet("A")) * number_segments; 167 168 // If everything is 0, use number_segments min-sized repeater 169 if(wire_length != 0) 170 { 171 // Set the initial number of segments based on isKeepParity 172 double last_min_size_delay = 0; 173 unsigned int iteration = 0; 174 175 // First set the repeater to the minimum driving strength 176 last_min_size_delay = delay; 177 178 Log::printLine(getInstanceName() + " -> Beginning Repeater Insertion"); 179 180 while(required_delay < delay) 181 { 182 Log::printLine(getInstanceName() + " -> Repeater Insertion Iteration " + (String)iteration + 183 ": Required delay = " + (String)required_delay + 184 ", Delay = " + (String)delay + 185 ", Slack = " + (String)(required_delay - delay) + 186 ", Number of repeaters = " + (String)number_segments); 187 188 // Size up if timing is not met 189 while(required_delay < delay) 190 { 191 if(m_repeater_->hasMaxDrivingStrength()) 192 { 193 break; 194 } 195 m_repeater_->increaseDrivingStrength(); 196 m_repeater_load_->setLoadCap(m_repeater_->getNet("A")->getTotalDownstreamCap()); 197 m_timing_tree_->performCritPathExtract(m_repeater_->getNet("A")); 198 delay = m_timing_tree_->calculateCritPathDelay(m_repeater_->getNet("A")) * number_segments; 199 200 iteration++; 201 Log::printLine(getInstanceName() + " -> Slack: " + (String)(required_delay - delay)); 202 } 203 // Increase number of segments if timing is not met 204 if(required_delay < delay) 205 { 206 number_segments += increment_segments; 207 m_repeater_->setMinDrivingStrength(); 208 m_repeater_->getNet("Y")->setDistributedCap(total_wire_cap / number_segments); 209 m_repeater_->getNet("Y")->setDistributedRes(total_wire_res / number_segments); 210 m_repeater_load_->setLoadCap(m_repeater_->getNet("A")->getTotalDownstreamCap()); 211 m_timing_tree_->performCritPathExtract(m_repeater_->getNet("A")); 212 delay = m_timing_tree_->calculateCritPathDelay(m_repeater_->getNet("A")) * number_segments; 213 214 // Abort if adding more min sized repeaters does not decrease the delay 215 if(delay > last_min_size_delay) 216 { 217 break; 218 } 219 last_min_size_delay = delay; 220 } 221 } 222 Log::printLine(getInstanceName() + " -> Repeater Insertion Ended after Iteration: " + (String)iteration + 223 ": Required delay = " + (String)required_delay + 224 ", Delay = " + (String)delay + 225 ", Slack = " + (String)(required_delay - delay) + 226 ", Number of repeaters = " + (String)number_segments); 227 228 // Print a warning if the timing is not met 229 if(required_delay < delay) 230 { 231 const String& warning_msg = "[Warning] " + getInstanceName() + " -> Timing not met" + 232 ": Required delay = " + (String)required_delay + 233 ", Delay = " + (String)delay + 234 ", Slack = " + (String)(required_delay - delay) + 235 ", Number of repeaters = " + (String)number_segments; 236 Log::printLine(std::cerr, warning_msg); 237 } 238 } 239 240 // Update electrical interfaces 241 getLoad("In_Cap")->setLoadCap(m_repeater_->getNet("A")->getTotalDownstreamCap()); 242 getDelay("In_to_Out_delay")->setDelay(delay); 243 getDriver("Out_Ron")->setOutputRes(m_repeater_->getDriver("Y_Ron")->getOutputRes() + (total_wire_res / number_segments)); 244 245 getGenProperties()->set("NumberSegments", number_segments); 246 247 // Update area, power results 248 resetElectricalAtomicResults(); 249 addElecticalAtomicResultValues(m_repeater_, number_segments * number_bits); 250 double wire_area = wire_length * (wire_width + wire_spacing) * number_bits; 251 addElecticalWireAtomicResultValue(wire_layer, wire_area); 252 253 return; 254 } 255 256 void RepeatedLink::useModel() 257 { 258 // Update the transition information for the modeled repeater 259 // Since we only modeled one repeater. So the transition information for 0->0 and 1->1 260 // is averaged out 261 const TransitionInfo& trans_In = getInputPort("In")->getTransitionInfo(); 262 double average_static_transition = (trans_In.getNumberTransitions00() + trans_In.getNumberTransitions11()) / 2.0; 263 TransitionInfo mod_trans_In(average_static_transition, trans_In.getNumberTransitions01(), average_static_transition); 264 m_repeater_->getInputPort("A")->setTransitionInfo(mod_trans_In); 265 m_repeater_->use(); 266 267 // Get parameters 268 unsigned int number_bits = getParameter("NumberBits").toUInt(); 269 unsigned int number_segments = getGenProperties()->get("NumberSegments").toUInt(); 270 271 // Propagate the transition information 272 propagateTransitionInfo(); 273 274 // Update leakage power 275 double power = 0.0; 276 power += m_repeater_->getNddPowerResult("Leakage")->calculateSum() * number_segments * number_bits; 277 getNddPowerResult("Leakage")->setValue(power); 278 279 // Update event result 280 double energy = 0.0; 281 energy += m_repeater_->getEventResult("INV")->calculateSum() * number_segments * number_bits; 282 getEventResult("Send")->setValue(energy); 283 284 return; 285 } 286 287 void RepeatedLink::propagateTransitionInfo() 288 { 289 unsigned int number_segments = getGenProperties()->get("NumberSegments"); 290 291 if((number_segments % 2) == 0) 292 { 293 propagatePortTransitionInfo("Out", "In"); 294 } 295 else 296 { 297 const TransitionInfo& trans_In = getInputPort("In")->getTransitionInfo(); 298 TransitionInfo trans_Out(trans_In.getNumberTransitions11(), trans_In.getNumberTransitions01(), trans_In.getNumberTransitions00()); 299 getOutputPort("Out")->setTransitionInfo(trans_Out); 300 } 301 return; 302 } 303 304} // namespace DSENT 305 306