1#include "model/optical/OpticalLinkBackendTx.h" 2 3#include "util/Constants.h" 4#include "model/PortInfo.h" 5#include "model/TransitionInfo.h" 6#include "model/EventInfo.h" 7#include "model/electrical/MuxTreeSerializer.h" 8#include "model/electrical/BarrelShifter.h" 9#include "model/electrical/Multiplexer.h" 10#include <cmath> 11 12namespace DSENT 13{ 14 // TODO: Kind of don't like the way thermal tuning is written here. Maybe will switch 15 // to curve fitting the CICC paper, which uses results from a monte-carlo sim 16 17 OpticalLinkBackendTx::OpticalLinkBackendTx(const String& instance_name_, const TechModel* tech_model_) 18 : ElectricalModel(instance_name_, tech_model_) 19 { 20 initParameters(); 21 initProperties(); 22 } 23 24 OpticalLinkBackendTx::~OpticalLinkBackendTx() 25 {} 26 27 void OpticalLinkBackendTx::initParameters() 28 { 29 addParameterName("InBits"); 30 addParameterName("CoreDataRate"); 31 addParameterName("LinkDataRate"); 32 addParameterName("RingTuningMethod"); 33 addParameterName("BitDuplicate"); 34 return; 35 } 36 37 void OpticalLinkBackendTx::initProperties() 38 { 39 return; 40 } 41 42 void OpticalLinkBackendTx::constructModel() 43 { 44 unsigned int in_bits = getParameter("InBits"); 45 double core_data_rate = getParameter("CoreDataRate"); 46 double link_data_rate = getParameter("LinkDataRate"); 47 const String& tuning_method = getParameter("RingTuningMethod");; 48 bool bit_duplicate = getParameter("BitDuplicate"); 49 50 // Calculate serialization ratio 51 unsigned int serialization_ratio = (unsigned int) floor(link_data_rate / core_data_rate); 52 ASSERT(serialization_ratio == link_data_rate / core_data_rate, 53 "[Error] " + getInstanceName() + " -> Cannot have non-integer serialization ratios " + 54 "(" + (String) (core_data_rate / link_data_rate) + ")!"); 55 56 // Calculate output width 57 ASSERT(floor((double) in_bits / serialization_ratio) == (double) in_bits / serialization_ratio, 58 "[Error] " + getInstanceName() + " -> Input width (" + (String) in_bits + ") " + 59 "must be a multiple of the serialization ratio (" + (String) serialization_ratio + ")!"); 60 unsigned int out_bits = in_bits / serialization_ratio; 61 62 getGenProperties()->set("SerializationRatio", serialization_ratio); 63 getGenProperties()->set("OutBits", out_bits); 64 65 // Create ports 66 createInputPort("In", makeNetIndex(0, in_bits-1)); 67 createInputPort("LinkCK"); 68 createOutputPort("Out", makeNetIndex(0, out_bits-1)); 69 70 //Create energy, power, and area results 71 createElectricalResults(); 72 // Create ring heating power cost 73 addNddPowerResult(new AtomicResult("RingTuning")); 74 // Create process bits event 75 createElectricalEventResult("ProcessBits"); 76 getEventInfo("ProcessBits")->setTransitionInfo("LinkCK", TransitionInfo(0.0, (double) serialization_ratio / 2.0, 0.0)); 77 // Set conditions during idle state 78 getEventInfo("Idle")->setStaticTransitionInfos(); 79 getEventInfo("Idle")->setTransitionInfo("LinkCK", TransitionInfo(0.0, (double) serialization_ratio / 2.0, 0.0)); 80 81 // Create serializer 82 const String& serializer_name = "Serializer"; 83 MuxTreeSerializer* serializer = new MuxTreeSerializer(serializer_name, getTechModel()); 84 serializer->setParameter("InBits", in_bits); 85 serializer->setParameter("InDataRate", core_data_rate); 86 serializer->setParameter("OutDataRate", link_data_rate); 87 serializer->setParameter("BitDuplicate", bit_duplicate); 88 serializer->construct(); 89 90 addSubInstances(serializer, 1.0); 91 addElectricalSubResults(serializer, 1.0); 92 getEventResult("ProcessBits")->addSubResult(serializer->getEventResult("Serialize"), serializer_name, 1.0); 93 94 if ((tuning_method == "ThermalWithBitReshuffle") || (tuning_method == "ElectricalAssistWithBitReshuffle")) 95 { 96 // If a bit reshuffling backend is present, create the reshuffling backend 97 unsigned int reorder_degree = getBitReorderDegree(); 98 99 // Create intermediate nets 100 createNet("SerializerIn", makeNetIndex(0, in_bits-1)); 101 createNet("ReorderIn", makeNetIndex(0, out_bits+reorder_degree-1)); 102 assign("ReorderIn", makeNetIndex(out_bits, out_bits+reorder_degree-1), "ReorderIn", makeNetIndex(0, reorder_degree-1)); 103 104 // Create barrelshifter 105 unsigned int shift_index_min = (unsigned int)ceil(log2(serialization_ratio)); 106 unsigned int shift_index_max = std::max(shift_index_min, (unsigned int) ceil(log2(in_bits)) - 1); 107 108 // Remember some things 109 getGenProperties()->set("ReorderDegree", reorder_degree); 110 getGenProperties()->set("ShiftIndexMin", shift_index_min); 111 getGenProperties()->set("ShiftIndexMax", shift_index_max); 112 113 const String& barrel_shift_name = "BarrelShifter"; 114 BarrelShifter* barrel_shift = new BarrelShifter(barrel_shift_name, getTechModel()); 115 barrel_shift->setParameter("NumberBits", in_bits); 116 barrel_shift->setParameter("ShiftIndexMax", shift_index_max); 117 barrel_shift->setParameter("ShiftIndexMin", shift_index_min); 118 barrel_shift->setParameter("BitDuplicate", bit_duplicate); 119 barrel_shift->construct(); 120 121 // Create bit reorder muxes 122 const String& reorder_mux_name = "ReorderMux"; 123 Multiplexer* reorder_mux = new Multiplexer(reorder_mux_name, getTechModel()); 124 reorder_mux->setParameter("NumberBits", out_bits); 125 reorder_mux->setParameter("NumberInputs", reorder_degree); 126 reorder_mux->setParameter("BitDuplicate", bit_duplicate); 127 reorder_mux->construct(); 128 129 // Connect barrelshifter 130 // TODO: Connect barrelshift shifts! 131 portConnect(barrel_shift, "In", "In"); 132 portConnect(barrel_shift, "Out", "SerializerIn"); 133 134 // Connect serializer 135 portConnect(serializer, "In", "SerializerIn"); 136 portConnect(serializer, "Out", "ReorderIn", makeNetIndex(0, out_bits-1)); 137 portConnect(serializer, "OutCK", "LinkCK"); 138 139 // Connect bit reorder muxes 140 // TODO: Connect re-order multiplex select signals! 141 for (unsigned int i = 0; i < reorder_degree; i++) 142 portConnect(reorder_mux, "In" + (String) i, "ReorderIn", makeNetIndex(i, i+out_bits-1)); 143 portConnect(reorder_mux, "Out", "Out"); 144 145 addSubInstances(barrel_shift, 1.0); 146 addSubInstances(reorder_mux, 1.0); 147 addElectricalSubResults(barrel_shift, 1.0); 148 addElectricalSubResults(reorder_mux, 1.0); 149 getEventResult("ProcessBits")->addSubResult(barrel_shift->getEventResult("BarrelShift"), barrel_shift_name, 1.0); 150 getEventResult("ProcessBits")->addSubResult(reorder_mux->getEventResult("Mux"), reorder_mux_name, 1.0); // This happens multiple times 151 } 152 else if ((tuning_method == "FullThermal") || (tuning_method == "AthermalWithTrim")) 153 { 154 // If no bit reshuffling backend is present, then just connect serializer up 155 portConnect(serializer, "In", "In"); 156 portConnect(serializer, "Out", "Out"); 157 portConnect(serializer, "OutCK", "LinkCK"); 158 } 159 else 160 { 161 ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown ring tuning method '" + tuning_method + "'!"); 162 } 163 164 return; 165 } 166 167 void OpticalLinkBackendTx::updateModel() 168 { 169 // Update everyone 170 Model::updateModel(); 171 // Update ring tuning power 172 getNddPowerResult("RingTuning")->setValue(getRingTuningPower()); 173 return; 174 } 175 176 void OpticalLinkBackendTx::propagateTransitionInfo() 177 { 178 // Get parameters 179 const String& tuning_method = getParameter("RingTuningMethod"); 180 181 // Update the serializer 182 if ((tuning_method == "ThermalWithBitReshuffle") || (tuning_method == "ElectricalAssistWithBitReshuffle")) 183 { 184 // Get generated properties 185 unsigned int reorder_degree = getGenProperties()->get("ReorderDegree").toUInt(); 186 unsigned int shift_index_min = getGenProperties()->get("ShiftIndexMin").toUInt(); 187 unsigned int shift_index_max = getGenProperties()->get("ShiftIndexMax").toUInt(); 188 189 // Update barrel shifter 190 const String& barrel_shift_name = "BarrelShifter"; 191 ElectricalModel* barrel_shift = (ElectricalModel*) getSubInstance(barrel_shift_name); 192 propagatePortTransitionInfo(barrel_shift, "In", "In"); 193 // Set shift transitions to be very low (since it is affected by slow temperature time constants) 194 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) 195 barrel_shift->getInputPort("Shift" + (String) i)->setTransitionInfo(TransitionInfo(0.499, 0.001, 0.499)); 196 barrel_shift->use(); 197 198 // Set serializer transition info 199 ElectricalModel* serializer = (ElectricalModel*) getSubInstance("Serializer"); 200 propagatePortTransitionInfo(serializer, "In", barrel_shift, "Out"); 201 propagatePortTransitionInfo(serializer, "OutCK", "LinkCK"); 202 serializer->use(); 203 204 // Reorder mux shift select bits 205 unsigned int reorder_sel_bits = (unsigned int)ceil(log2(reorder_degree)); 206 207 // Reorder mux probabilities 208 const String& reorder_mux_name = "ReorderMux"; 209 ElectricalModel* reorder_mux = (ElectricalModel*) getSubInstance(reorder_mux_name); 210 for (unsigned int i = 0; i < reorder_degree; ++i) 211 propagatePortTransitionInfo(reorder_mux, "In" + (String) i, serializer, "Out"); 212 // Set select transitions to be 0, since these are statically configured 213 for (unsigned int i = 0; i < reorder_sel_bits; ++i) 214 reorder_mux->getInputPort("Sel" + (String) i)->setTransitionInfo(TransitionInfo(0.5, 0.0, 0.5)); 215 reorder_mux->use(); 216 217 // Set output transition info 218 propagatePortTransitionInfo("Out", reorder_mux, "Out"); 219 } 220 else if ((tuning_method == "FullThermal") || (tuning_method == "AthermalWithTrim")) 221 { 222 // Set serializer transition info 223 ElectricalModel* serializer = (ElectricalModel*) getSubInstance("Serializer"); 224 propagatePortTransitionInfo(serializer, "In", "In"); 225 propagatePortTransitionInfo(serializer, "OutCK", "LinkCK"); 226 serializer->use(); 227 228 // Set output transition info 229 propagatePortTransitionInfo("Out", serializer, "Out"); 230 } 231 232 return; 233 } 234 235 double OpticalLinkBackendTx::getRingTuningPower() 236 { 237 // Get properties 238 const String& tuning_method = getParameter("RingTuningMethod");; 239 unsigned int number_rings = getGenProperties()->get("OutBits"); 240 241 // Get tech model parameters 242 double R = getTechModel()->get("Ring->Radius"); 243 double n_g = getTechModel()->get("Ring->GroupIndex"); 244 double heating_efficiency = getTechModel()->get("Ring->HeatingEfficiency"); 245 // This can actually be derived if we know thermo-optic coefficient (delta n / delta T) 246 double tuning_efficiency = getTechModel()->get("Ring->TuningEfficiency"); 247 double sigma_r_local = getTechModel()->get("Ring->LocalVariationSigma"); 248 double sigma_r_systematic = getTechModel()->get("Ring->SystematicVariationSigma"); 249 double T_max = getTechModel()->get("Ring->TemperatureMax"); 250 double T_min = getTechModel()->get("Ring->TemperatureMin"); 251 double T = getTechModel()->get("Temperature"); 252 253 // Get constants 254 double c = Constants::c; 255 double pi = Constants::pi; 256 257 double tuning_power = 0.0; 258 259 if (tuning_method == "ThermalWithBitReshuffle") 260 { 261 // When an electrical backend is present, rings only have to tune to the nearest channel 262 // This can be approximated as each ring tuning to something exactly 1 channel away 263 264 // Setup calculations 265 double L = 2 * pi * R; // Optical length 266 double FSR = c / (n_g * L); // Free spectral range 267 double freq_sep = FSR / number_rings; // Channel separation 268 269 // Calculate tuning power 270 tuning_power = number_rings * freq_sep / (tuning_efficiency * heating_efficiency); 271 } 272 else if (tuning_method == "ElectricalAssistWithBitReshuffle") 273 { 274 // Electrical assistance allows for a fraction of the tuning range to be 275 // covered electrically. This is most pronounced when the tuning range is small, 276 // such is the case when bit reshuffling is applied. The electrically 277 // assisted part of it pretty much comes for free... 278 279 // Get electrically tunable range 280 double max_assist = getTechModel()->get("Ring->MaxElectricallyTunableFreq"); 281 282 // Setup calculations 283 double L = 2 * pi * R; // Optical length 284 double FSR = c / (n_g * L); // Free spectral range 285 double freq_sep = FSR / number_rings; // Channel separation 286 double heating_range = std::max(0.0, freq_sep - max_assist); // The distance needed to bridge using heaters 287 288 // Calculate tuning power, which is really only the power spent on heating since 289 // distance tuned electrically is pretty much free 290 tuning_power = number_rings * heating_range / (tuning_efficiency * heating_efficiency); 291 } 292 else if (tuning_method == "FullThermal") 293 { 294 // If there is no bit reshuffling backend, each ring must tune to an 295 // absolute channel frequency. Since we can only heat rings (and not cool), 296 // we can only red-shift (decrease frequency). Thus, a fabrication bias 297 // must be applied such that under any process and temperature corner, the 298 // ring resonance remains above channel resonance 299 // I'll use 3 sigmas of sigma_r_local and sigma_r_systematic, and bias against 300 // the full temperature range 301 double fabrication_bias_freq = 3.0 * sqrt(pow(sigma_r_local, 2) + pow(sigma_r_systematic, 2)) + 302 (T_max - T_min) * tuning_efficiency; 303 304 // The local/systematic variations are 0 on average. Thus, the tuning distance can be calculated as 305 double tuning_distance = fabrication_bias_freq - (T - T_min) * tuning_efficiency; 306 307 // Tuning power needed is just the number of rings * tuning distance / (tuning and heating efficiencies) 308 tuning_power = number_rings * tuning_distance / (tuning_efficiency * heating_efficiency); 309 } 310 else if (tuning_method == "AthermalWithTrim") 311 { 312 // Athermal! Each ring's process variations are trimmed! Everything is free! 313 // Basically an ideal scenario 314 tuning_power = 0; 315 } 316 else 317 { 318 ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown ring tuning method '" + tuning_method + "'!"); 319 } 320 321 return tuning_power; 322 } 323 324 unsigned int OpticalLinkBackendTx::getBitReorderDegree() 325 { 326 // Get properties 327 unsigned int number_rings = getGenProperties()->get("OutBits"); 328 329 // Get tech model parameters 330 double R = getTechModel()->get("Ring->Radius"); 331 double n_g = getTechModel()->get("Ring->GroupIndex"); 332 // This can actually be derived if we know thermo-optic coefficient (delta n / delta T) 333 double sigma_r_local = getTechModel()->get("Ring->LocalVariationSigma"); 334 335 // Get constants 336 double c = Constants::c; 337 double pi = Constants::pi; 338 339 // Calculates the degree of bit re-order multiplexing needed for bit-reshuffling backend 340 // Bit reshuffling tuning is largely unaffected by sigma_r_systematic. However, sigma_r_local 341 // Can potentially throw each ring to a channel several channels away. This just calculates 342 // the degree of bit reorder muxing needed to realign bits in the correct order 343 344 // Setup calculations 345 double L = 2 * pi * R; // Optical length 346 double FSR = c / (n_g * L); // Free spectral range 347 double freq_sep = FSR / number_rings; // Channel separation 348 // Using 4 sigmas as the worst re-ordering case (must double to get both sides) 349 unsigned int worst_case_channels = (unsigned int)ceil(2.0 * 4.0 * sigma_r_local / freq_sep); 350 351 return worst_case_channels; 352 } 353 354} // namespace DSENT 355
| 22#include "model/optical/OpticalLinkBackendTx.h" 23 24#include "util/Constants.h" 25#include "model/PortInfo.h" 26#include "model/TransitionInfo.h" 27#include "model/EventInfo.h" 28#include "model/electrical/MuxTreeSerializer.h" 29#include "model/electrical/BarrelShifter.h" 30#include "model/electrical/Multiplexer.h" 31#include <cmath> 32 33namespace DSENT 34{ 35 // TODO: Kind of don't like the way thermal tuning is written here. Maybe will switch 36 // to curve fitting the CICC paper, which uses results from a monte-carlo sim 37 38 OpticalLinkBackendTx::OpticalLinkBackendTx(const String& instance_name_, const TechModel* tech_model_) 39 : ElectricalModel(instance_name_, tech_model_) 40 { 41 initParameters(); 42 initProperties(); 43 } 44 45 OpticalLinkBackendTx::~OpticalLinkBackendTx() 46 {} 47 48 void OpticalLinkBackendTx::initParameters() 49 { 50 addParameterName("InBits"); 51 addParameterName("CoreDataRate"); 52 addParameterName("LinkDataRate"); 53 addParameterName("RingTuningMethod"); 54 addParameterName("BitDuplicate"); 55 return; 56 } 57 58 void OpticalLinkBackendTx::initProperties() 59 { 60 return; 61 } 62 63 void OpticalLinkBackendTx::constructModel() 64 { 65 unsigned int in_bits = getParameter("InBits"); 66 double core_data_rate = getParameter("CoreDataRate"); 67 double link_data_rate = getParameter("LinkDataRate"); 68 const String& tuning_method = getParameter("RingTuningMethod");; 69 bool bit_duplicate = getParameter("BitDuplicate"); 70 71 // Calculate serialization ratio 72 unsigned int serialization_ratio = (unsigned int) floor(link_data_rate / core_data_rate); 73 ASSERT(serialization_ratio == link_data_rate / core_data_rate, 74 "[Error] " + getInstanceName() + " -> Cannot have non-integer serialization ratios " + 75 "(" + (String) (core_data_rate / link_data_rate) + ")!"); 76 77 // Calculate output width 78 ASSERT(floor((double) in_bits / serialization_ratio) == (double) in_bits / serialization_ratio, 79 "[Error] " + getInstanceName() + " -> Input width (" + (String) in_bits + ") " + 80 "must be a multiple of the serialization ratio (" + (String) serialization_ratio + ")!"); 81 unsigned int out_bits = in_bits / serialization_ratio; 82 83 getGenProperties()->set("SerializationRatio", serialization_ratio); 84 getGenProperties()->set("OutBits", out_bits); 85 86 // Create ports 87 createInputPort("In", makeNetIndex(0, in_bits-1)); 88 createInputPort("LinkCK"); 89 createOutputPort("Out", makeNetIndex(0, out_bits-1)); 90 91 //Create energy, power, and area results 92 createElectricalResults(); 93 // Create ring heating power cost 94 addNddPowerResult(new AtomicResult("RingTuning")); 95 // Create process bits event 96 createElectricalEventResult("ProcessBits"); 97 getEventInfo("ProcessBits")->setTransitionInfo("LinkCK", TransitionInfo(0.0, (double) serialization_ratio / 2.0, 0.0)); 98 // Set conditions during idle state 99 getEventInfo("Idle")->setStaticTransitionInfos(); 100 getEventInfo("Idle")->setTransitionInfo("LinkCK", TransitionInfo(0.0, (double) serialization_ratio / 2.0, 0.0)); 101 102 // Create serializer 103 const String& serializer_name = "Serializer"; 104 MuxTreeSerializer* serializer = new MuxTreeSerializer(serializer_name, getTechModel()); 105 serializer->setParameter("InBits", in_bits); 106 serializer->setParameter("InDataRate", core_data_rate); 107 serializer->setParameter("OutDataRate", link_data_rate); 108 serializer->setParameter("BitDuplicate", bit_duplicate); 109 serializer->construct(); 110 111 addSubInstances(serializer, 1.0); 112 addElectricalSubResults(serializer, 1.0); 113 getEventResult("ProcessBits")->addSubResult(serializer->getEventResult("Serialize"), serializer_name, 1.0); 114 115 if ((tuning_method == "ThermalWithBitReshuffle") || (tuning_method == "ElectricalAssistWithBitReshuffle")) 116 { 117 // If a bit reshuffling backend is present, create the reshuffling backend 118 unsigned int reorder_degree = getBitReorderDegree(); 119 120 // Create intermediate nets 121 createNet("SerializerIn", makeNetIndex(0, in_bits-1)); 122 createNet("ReorderIn", makeNetIndex(0, out_bits+reorder_degree-1)); 123 assign("ReorderIn", makeNetIndex(out_bits, out_bits+reorder_degree-1), "ReorderIn", makeNetIndex(0, reorder_degree-1)); 124 125 // Create barrelshifter 126 unsigned int shift_index_min = (unsigned int)ceil(log2(serialization_ratio)); 127 unsigned int shift_index_max = std::max(shift_index_min, (unsigned int) ceil(log2(in_bits)) - 1); 128 129 // Remember some things 130 getGenProperties()->set("ReorderDegree", reorder_degree); 131 getGenProperties()->set("ShiftIndexMin", shift_index_min); 132 getGenProperties()->set("ShiftIndexMax", shift_index_max); 133 134 const String& barrel_shift_name = "BarrelShifter"; 135 BarrelShifter* barrel_shift = new BarrelShifter(barrel_shift_name, getTechModel()); 136 barrel_shift->setParameter("NumberBits", in_bits); 137 barrel_shift->setParameter("ShiftIndexMax", shift_index_max); 138 barrel_shift->setParameter("ShiftIndexMin", shift_index_min); 139 barrel_shift->setParameter("BitDuplicate", bit_duplicate); 140 barrel_shift->construct(); 141 142 // Create bit reorder muxes 143 const String& reorder_mux_name = "ReorderMux"; 144 Multiplexer* reorder_mux = new Multiplexer(reorder_mux_name, getTechModel()); 145 reorder_mux->setParameter("NumberBits", out_bits); 146 reorder_mux->setParameter("NumberInputs", reorder_degree); 147 reorder_mux->setParameter("BitDuplicate", bit_duplicate); 148 reorder_mux->construct(); 149 150 // Connect barrelshifter 151 // TODO: Connect barrelshift shifts! 152 portConnect(barrel_shift, "In", "In"); 153 portConnect(barrel_shift, "Out", "SerializerIn"); 154 155 // Connect serializer 156 portConnect(serializer, "In", "SerializerIn"); 157 portConnect(serializer, "Out", "ReorderIn", makeNetIndex(0, out_bits-1)); 158 portConnect(serializer, "OutCK", "LinkCK"); 159 160 // Connect bit reorder muxes 161 // TODO: Connect re-order multiplex select signals! 162 for (unsigned int i = 0; i < reorder_degree; i++) 163 portConnect(reorder_mux, "In" + (String) i, "ReorderIn", makeNetIndex(i, i+out_bits-1)); 164 portConnect(reorder_mux, "Out", "Out"); 165 166 addSubInstances(barrel_shift, 1.0); 167 addSubInstances(reorder_mux, 1.0); 168 addElectricalSubResults(barrel_shift, 1.0); 169 addElectricalSubResults(reorder_mux, 1.0); 170 getEventResult("ProcessBits")->addSubResult(barrel_shift->getEventResult("BarrelShift"), barrel_shift_name, 1.0); 171 getEventResult("ProcessBits")->addSubResult(reorder_mux->getEventResult("Mux"), reorder_mux_name, 1.0); // This happens multiple times 172 } 173 else if ((tuning_method == "FullThermal") || (tuning_method == "AthermalWithTrim")) 174 { 175 // If no bit reshuffling backend is present, then just connect serializer up 176 portConnect(serializer, "In", "In"); 177 portConnect(serializer, "Out", "Out"); 178 portConnect(serializer, "OutCK", "LinkCK"); 179 } 180 else 181 { 182 ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown ring tuning method '" + tuning_method + "'!"); 183 } 184 185 return; 186 } 187 188 void OpticalLinkBackendTx::updateModel() 189 { 190 // Update everyone 191 Model::updateModel(); 192 // Update ring tuning power 193 getNddPowerResult("RingTuning")->setValue(getRingTuningPower()); 194 return; 195 } 196 197 void OpticalLinkBackendTx::propagateTransitionInfo() 198 { 199 // Get parameters 200 const String& tuning_method = getParameter("RingTuningMethod"); 201 202 // Update the serializer 203 if ((tuning_method == "ThermalWithBitReshuffle") || (tuning_method == "ElectricalAssistWithBitReshuffle")) 204 { 205 // Get generated properties 206 unsigned int reorder_degree = getGenProperties()->get("ReorderDegree").toUInt(); 207 unsigned int shift_index_min = getGenProperties()->get("ShiftIndexMin").toUInt(); 208 unsigned int shift_index_max = getGenProperties()->get("ShiftIndexMax").toUInt(); 209 210 // Update barrel shifter 211 const String& barrel_shift_name = "BarrelShifter"; 212 ElectricalModel* barrel_shift = (ElectricalModel*) getSubInstance(barrel_shift_name); 213 propagatePortTransitionInfo(barrel_shift, "In", "In"); 214 // Set shift transitions to be very low (since it is affected by slow temperature time constants) 215 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) 216 barrel_shift->getInputPort("Shift" + (String) i)->setTransitionInfo(TransitionInfo(0.499, 0.001, 0.499)); 217 barrel_shift->use(); 218 219 // Set serializer transition info 220 ElectricalModel* serializer = (ElectricalModel*) getSubInstance("Serializer"); 221 propagatePortTransitionInfo(serializer, "In", barrel_shift, "Out"); 222 propagatePortTransitionInfo(serializer, "OutCK", "LinkCK"); 223 serializer->use(); 224 225 // Reorder mux shift select bits 226 unsigned int reorder_sel_bits = (unsigned int)ceil(log2(reorder_degree)); 227 228 // Reorder mux probabilities 229 const String& reorder_mux_name = "ReorderMux"; 230 ElectricalModel* reorder_mux = (ElectricalModel*) getSubInstance(reorder_mux_name); 231 for (unsigned int i = 0; i < reorder_degree; ++i) 232 propagatePortTransitionInfo(reorder_mux, "In" + (String) i, serializer, "Out"); 233 // Set select transitions to be 0, since these are statically configured 234 for (unsigned int i = 0; i < reorder_sel_bits; ++i) 235 reorder_mux->getInputPort("Sel" + (String) i)->setTransitionInfo(TransitionInfo(0.5, 0.0, 0.5)); 236 reorder_mux->use(); 237 238 // Set output transition info 239 propagatePortTransitionInfo("Out", reorder_mux, "Out"); 240 } 241 else if ((tuning_method == "FullThermal") || (tuning_method == "AthermalWithTrim")) 242 { 243 // Set serializer transition info 244 ElectricalModel* serializer = (ElectricalModel*) getSubInstance("Serializer"); 245 propagatePortTransitionInfo(serializer, "In", "In"); 246 propagatePortTransitionInfo(serializer, "OutCK", "LinkCK"); 247 serializer->use(); 248 249 // Set output transition info 250 propagatePortTransitionInfo("Out", serializer, "Out"); 251 } 252 253 return; 254 } 255 256 double OpticalLinkBackendTx::getRingTuningPower() 257 { 258 // Get properties 259 const String& tuning_method = getParameter("RingTuningMethod");; 260 unsigned int number_rings = getGenProperties()->get("OutBits"); 261 262 // Get tech model parameters 263 double R = getTechModel()->get("Ring->Radius"); 264 double n_g = getTechModel()->get("Ring->GroupIndex"); 265 double heating_efficiency = getTechModel()->get("Ring->HeatingEfficiency"); 266 // This can actually be derived if we know thermo-optic coefficient (delta n / delta T) 267 double tuning_efficiency = getTechModel()->get("Ring->TuningEfficiency"); 268 double sigma_r_local = getTechModel()->get("Ring->LocalVariationSigma"); 269 double sigma_r_systematic = getTechModel()->get("Ring->SystematicVariationSigma"); 270 double T_max = getTechModel()->get("Ring->TemperatureMax"); 271 double T_min = getTechModel()->get("Ring->TemperatureMin"); 272 double T = getTechModel()->get("Temperature"); 273 274 // Get constants 275 double c = Constants::c; 276 double pi = Constants::pi; 277 278 double tuning_power = 0.0; 279 280 if (tuning_method == "ThermalWithBitReshuffle") 281 { 282 // When an electrical backend is present, rings only have to tune to the nearest channel 283 // This can be approximated as each ring tuning to something exactly 1 channel away 284 285 // Setup calculations 286 double L = 2 * pi * R; // Optical length 287 double FSR = c / (n_g * L); // Free spectral range 288 double freq_sep = FSR / number_rings; // Channel separation 289 290 // Calculate tuning power 291 tuning_power = number_rings * freq_sep / (tuning_efficiency * heating_efficiency); 292 } 293 else if (tuning_method == "ElectricalAssistWithBitReshuffle") 294 { 295 // Electrical assistance allows for a fraction of the tuning range to be 296 // covered electrically. This is most pronounced when the tuning range is small, 297 // such is the case when bit reshuffling is applied. The electrically 298 // assisted part of it pretty much comes for free... 299 300 // Get electrically tunable range 301 double max_assist = getTechModel()->get("Ring->MaxElectricallyTunableFreq"); 302 303 // Setup calculations 304 double L = 2 * pi * R; // Optical length 305 double FSR = c / (n_g * L); // Free spectral range 306 double freq_sep = FSR / number_rings; // Channel separation 307 double heating_range = std::max(0.0, freq_sep - max_assist); // The distance needed to bridge using heaters 308 309 // Calculate tuning power, which is really only the power spent on heating since 310 // distance tuned electrically is pretty much free 311 tuning_power = number_rings * heating_range / (tuning_efficiency * heating_efficiency); 312 } 313 else if (tuning_method == "FullThermal") 314 { 315 // If there is no bit reshuffling backend, each ring must tune to an 316 // absolute channel frequency. Since we can only heat rings (and not cool), 317 // we can only red-shift (decrease frequency). Thus, a fabrication bias 318 // must be applied such that under any process and temperature corner, the 319 // ring resonance remains above channel resonance 320 // I'll use 3 sigmas of sigma_r_local and sigma_r_systematic, and bias against 321 // the full temperature range 322 double fabrication_bias_freq = 3.0 * sqrt(pow(sigma_r_local, 2) + pow(sigma_r_systematic, 2)) + 323 (T_max - T_min) * tuning_efficiency; 324 325 // The local/systematic variations are 0 on average. Thus, the tuning distance can be calculated as 326 double tuning_distance = fabrication_bias_freq - (T - T_min) * tuning_efficiency; 327 328 // Tuning power needed is just the number of rings * tuning distance / (tuning and heating efficiencies) 329 tuning_power = number_rings * tuning_distance / (tuning_efficiency * heating_efficiency); 330 } 331 else if (tuning_method == "AthermalWithTrim") 332 { 333 // Athermal! Each ring's process variations are trimmed! Everything is free! 334 // Basically an ideal scenario 335 tuning_power = 0; 336 } 337 else 338 { 339 ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown ring tuning method '" + tuning_method + "'!"); 340 } 341 342 return tuning_power; 343 } 344 345 unsigned int OpticalLinkBackendTx::getBitReorderDegree() 346 { 347 // Get properties 348 unsigned int number_rings = getGenProperties()->get("OutBits"); 349 350 // Get tech model parameters 351 double R = getTechModel()->get("Ring->Radius"); 352 double n_g = getTechModel()->get("Ring->GroupIndex"); 353 // This can actually be derived if we know thermo-optic coefficient (delta n / delta T) 354 double sigma_r_local = getTechModel()->get("Ring->LocalVariationSigma"); 355 356 // Get constants 357 double c = Constants::c; 358 double pi = Constants::pi; 359 360 // Calculates the degree of bit re-order multiplexing needed for bit-reshuffling backend 361 // Bit reshuffling tuning is largely unaffected by sigma_r_systematic. However, sigma_r_local 362 // Can potentially throw each ring to a channel several channels away. This just calculates 363 // the degree of bit reorder muxing needed to realign bits in the correct order 364 365 // Setup calculations 366 double L = 2 * pi * R; // Optical length 367 double FSR = c / (n_g * L); // Free spectral range 368 double freq_sep = FSR / number_rings; // Channel separation 369 // Using 4 sigmas as the worst re-ordering case (must double to get both sides) 370 unsigned int worst_case_channels = (unsigned int)ceil(2.0 * 4.0 * sigma_r_local / freq_sep); 371 372 return worst_case_channels; 373 } 374 375} // namespace DSENT 376
|