RingModulator.cc revision 10447
110447Snilay@cs.wisc.edu#include "model/optical/RingModulator.h" 210447Snilay@cs.wisc.edu 310447Snilay@cs.wisc.edu#include <cmath> 410447Snilay@cs.wisc.edu 510447Snilay@cs.wisc.edu#include "util/Constants.h" 610447Snilay@cs.wisc.edu#include "model/PortInfo.h" 710447Snilay@cs.wisc.edu#include "model/TransitionInfo.h" 810447Snilay@cs.wisc.edu#include "model/EventInfo.h" 910447Snilay@cs.wisc.edu#include "model/std_cells/StdCell.h" 1010447Snilay@cs.wisc.edu#include "model/std_cells/StdCellLib.h" 1110447Snilay@cs.wisc.edu#include "model/optical_graph/OpticalWaveguide.h" 1210447Snilay@cs.wisc.edu#include "model/optical_graph/OpticalModulator.h" 1310447Snilay@cs.wisc.edu#include "model/optical_graph/OpticalFilter.h" 1410447Snilay@cs.wisc.edu#include "model/optical_graph/OpticalTransmitter.h" 1510447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalNet.h" 1610447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalLoad.h" 1710447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalTimingTree.h" 1810447Snilay@cs.wisc.edu 1910447Snilay@cs.wisc.edunamespace DSENT 2010447Snilay@cs.wisc.edu{ 2110447Snilay@cs.wisc.edu using std::max; 2210447Snilay@cs.wisc.edu using std::min; 2310447Snilay@cs.wisc.edu 2410447Snilay@cs.wisc.edu // TODO: Don't like the way this is written right now. Probably fix in a future version 2510447Snilay@cs.wisc.edu 2610447Snilay@cs.wisc.edu RingModulator::RingModulator(const String& instance_name_, const TechModel* tech_model_) 2710447Snilay@cs.wisc.edu : OpticalModel(instance_name_, tech_model_) 2810447Snilay@cs.wisc.edu { 2910447Snilay@cs.wisc.edu initParameters(); 3010447Snilay@cs.wisc.edu initProperties(); 3110447Snilay@cs.wisc.edu } 3210447Snilay@cs.wisc.edu 3310447Snilay@cs.wisc.edu RingModulator::~RingModulator() 3410447Snilay@cs.wisc.edu {} 3510447Snilay@cs.wisc.edu 3610447Snilay@cs.wisc.edu void RingModulator::initParameters() 3710447Snilay@cs.wisc.edu { 3810447Snilay@cs.wisc.edu addParameterName("DataRate"); 3910447Snilay@cs.wisc.edu addParameterName("InStart"); 4010447Snilay@cs.wisc.edu addParameterName("InEnd"); 4110447Snilay@cs.wisc.edu addParameterName("ModStart"); 4210447Snilay@cs.wisc.edu addParameterName("ModEnd"); 4310447Snilay@cs.wisc.edu addParameterName("OptimizeLoss", "TRUE"); 4410447Snilay@cs.wisc.edu return; 4510447Snilay@cs.wisc.edu } 4610447Snilay@cs.wisc.edu 4710447Snilay@cs.wisc.edu void RingModulator::initProperties() 4810447Snilay@cs.wisc.edu { 4910447Snilay@cs.wisc.edu addPropertyName("ExtinctionRatio", 6); //default properties 5010447Snilay@cs.wisc.edu addPropertyName("InsertionLoss", 2); //default properties 5110447Snilay@cs.wisc.edu return; 5210447Snilay@cs.wisc.edu } 5310447Snilay@cs.wisc.edu 5410447Snilay@cs.wisc.edu void RingModulator::constructModel() 5510447Snilay@cs.wisc.edu { 5610447Snilay@cs.wisc.edu // Create electrical results 5710447Snilay@cs.wisc.edu createElectricalAtomicResults(); 5810447Snilay@cs.wisc.edu // Create Area result 5910447Snilay@cs.wisc.edu addAreaResult(new AtomicResult("Photonic")); 6010447Snilay@cs.wisc.edu // Create Modulate result 6110447Snilay@cs.wisc.edu createElectricalEventAtomicResult("Modulate"); 6210447Snilay@cs.wisc.edu 6310447Snilay@cs.wisc.edu // Get parameters 6410447Snilay@cs.wisc.edu WavelengthGroup in_wavelengths = makeWavelengthGroup(getParameter("InStart"), getParameter("InEnd")); 6510447Snilay@cs.wisc.edu WavelengthGroup mod_wavelengths = makeWavelengthGroup(getParameter("ModStart"), getParameter("ModEnd")); 6610447Snilay@cs.wisc.edu int number_wavelengths = mod_wavelengths.second - mod_wavelengths.first + 1; 6710447Snilay@cs.wisc.edu bool optimize_loss = getParameter("OptimizeLoss"); 6810447Snilay@cs.wisc.edu 6910447Snilay@cs.wisc.edu getGenProperties()->set("NumberWavelengths", number_wavelengths); 7010447Snilay@cs.wisc.edu 7110447Snilay@cs.wisc.edu // Create optical ports 7210447Snilay@cs.wisc.edu createOpticalInputPort( "In", in_wavelengths); 7310447Snilay@cs.wisc.edu createOpticalOutputPort( "Out", in_wavelengths); 7410447Snilay@cs.wisc.edu // Create the filter and modulator 7510447Snilay@cs.wisc.edu createFilter( "RingFilter", in_wavelengths, true, mod_wavelengths); 7610447Snilay@cs.wisc.edu createModulator( "RingModulator", mod_wavelengths, optimize_loss, this); 7710447Snilay@cs.wisc.edu createWaveguide( "RingTemp", mod_wavelengths); 7810447Snilay@cs.wisc.edu OpticalFilter* ring_filter = getFilter("RingFilter"); 7910447Snilay@cs.wisc.edu OpticalModulator* ring_modulator = getModulator("RingModulator"); 8010447Snilay@cs.wisc.edu // Connect the filter and modulator 8110447Snilay@cs.wisc.edu getWaveguide("In")->addDownstreamNode(ring_filter); 8210447Snilay@cs.wisc.edu ring_filter->addDownstreamNode(getWaveguide("Out")); 8310447Snilay@cs.wisc.edu ring_filter->setDropPort(ring_modulator); 8410447Snilay@cs.wisc.edu ring_modulator->addDownstreamNode(getWaveguide("Out")); 8510447Snilay@cs.wisc.edu 8610447Snilay@cs.wisc.edu // Create electrical ports 8710447Snilay@cs.wisc.edu createInputPort( "In", makeNetIndex(0, number_wavelengths-1)); 8810447Snilay@cs.wisc.edu // Create driver 8910447Snilay@cs.wisc.edu createNet("PredriverIn"); 9010447Snilay@cs.wisc.edu // VFI from In to PredriverIn 9110447Snilay@cs.wisc.edu assignVirtualFanin("PredriverIn", "In"); 9210447Snilay@cs.wisc.edu // Create input load (due to predrivers) 9310447Snilay@cs.wisc.edu createLoad("PredriverCap"); 9410447Snilay@cs.wisc.edu getNet("PredriverIn")->addDownstreamNode(getLoad("PredriverCap")); 9510447Snilay@cs.wisc.edu 9610447Snilay@cs.wisc.edu // Precompute some values 9710447Snilay@cs.wisc.edu precomputeTech(); 9810447Snilay@cs.wisc.edu 9910447Snilay@cs.wisc.edu return; 10010447Snilay@cs.wisc.edu } 10110447Snilay@cs.wisc.edu 10210447Snilay@cs.wisc.edu void RingModulator::updateModel() 10310447Snilay@cs.wisc.edu { 10410447Snilay@cs.wisc.edu // Get properties 10510447Snilay@cs.wisc.edu double ER_dB = getProperty("ExtinctionRatio").toDouble(); 10610447Snilay@cs.wisc.edu double IL_dB = getProperty("InsertionLoss").toDouble(); 10710447Snilay@cs.wisc.edu 10810447Snilay@cs.wisc.edu // Get Gen properties 10910447Snilay@cs.wisc.edu int number_wavelengths = getGenProperties()->get("NumberWavelengths"); 11010447Snilay@cs.wisc.edu 11110447Snilay@cs.wisc.edu // Get tech model parameters 11210447Snilay@cs.wisc.edu double ring_area = getTechModel()->get("Ring->Area").toDouble(); 11310447Snilay@cs.wisc.edu double thru_loss = getTechModel()->get("Ring->ThroughLoss").toDouble(); 11410447Snilay@cs.wisc.edu 11510447Snilay@cs.wisc.edu // Design the modulator and the modulator driver 11610447Snilay@cs.wisc.edu bool success = designModulator(IL_dB, ER_dB); 11710447Snilay@cs.wisc.edu getGenProperties()->set("Success", success); 11810447Snilay@cs.wisc.edu 11910447Snilay@cs.wisc.edu // If not successful, make the modulate energy extremely large 12010447Snilay@cs.wisc.edu if (!success) getEventResult("Modulate")->setValue(1e99); 12110447Snilay@cs.wisc.edu 12210447Snilay@cs.wisc.edu // Update losses 12310447Snilay@cs.wisc.edu // Connect the filter and modulator 12410447Snilay@cs.wisc.edu OpticalFilter* ring_filter = getFilter("RingFilter"); 12510447Snilay@cs.wisc.edu ring_filter->setLoss(thru_loss * number_wavelengths); 12610447Snilay@cs.wisc.edu ring_filter->setDropLoss(thru_loss * number_wavelengths); // Assume worst-case through loss for a dropped wavelength 12710447Snilay@cs.wisc.edu // Update area 12810447Snilay@cs.wisc.edu getAreaResult("Photonic")->setValue(ring_area * (number_wavelengths)); 12910447Snilay@cs.wisc.edu } 13010447Snilay@cs.wisc.edu 13110447Snilay@cs.wisc.edu void RingModulator::useModel() 13210447Snilay@cs.wisc.edu { 13310447Snilay@cs.wisc.edu // Propagate the transition info and get the 0->1 transtion count 13410447Snilay@cs.wisc.edu propagateTransitionInfo(); 13510447Snilay@cs.wisc.edu double P_In = getInputPort("In")->getTransitionInfo().getProbability1(); 13610447Snilay@cs.wisc.edu double P_num_trans_01 = getInputPort("In")->getTransitionInfo().getNumberTransitions01(); 13710447Snilay@cs.wisc.edu 13810447Snilay@cs.wisc.edu // Get Gen properties 13910447Snilay@cs.wisc.edu int number_wavelengths = getGenProperties()->get("NumberWavelengths"); 14010447Snilay@cs.wisc.edu 14110447Snilay@cs.wisc.edu // If I can't build it...then it is infinitely expensive! 14210447Snilay@cs.wisc.edu bool success = getGenProperties()->get("Success"); 14310447Snilay@cs.wisc.edu double driver_size = 1e99; 14410447Snilay@cs.wisc.edu double total_predriver_size = 1e99; 14510447Snilay@cs.wisc.edu if (success) 14610447Snilay@cs.wisc.edu { 14710447Snilay@cs.wisc.edu driver_size = getGenProperties()->get("DriverSize"); 14810447Snilay@cs.wisc.edu total_predriver_size = getGenProperties()->get("TotalPredriverSize"); 14910447Snilay@cs.wisc.edu } 15010447Snilay@cs.wisc.edu 15110447Snilay@cs.wisc.edu // Get parameters corresponding to a unit-inverter 15210447Snilay@cs.wisc.edu double unit_leak_0 = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Leakage->!A"); 15310447Snilay@cs.wisc.edu double unit_leak_1 = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Leakage->A"); 15410447Snilay@cs.wisc.edu 15510447Snilay@cs.wisc.edu // Approximate leakage 15610447Snilay@cs.wisc.edu double total_leakage = number_wavelengths * 0.5 * ((driver_size + total_predriver_size) * P_In * unit_leak_1 + 15710447Snilay@cs.wisc.edu (driver_size + total_predriver_size) * (1 - P_In) * unit_leak_0); 15810447Snilay@cs.wisc.edu 15910447Snilay@cs.wisc.edu getNddPowerResult("Leakage")->setValue(total_leakage); 16010447Snilay@cs.wisc.edu getEventResult("Modulate")->setValue(calcModulatorEnergy() * P_num_trans_01); 16110447Snilay@cs.wisc.edu 16210447Snilay@cs.wisc.edu return; 16310447Snilay@cs.wisc.edu } 16410447Snilay@cs.wisc.edu 16510447Snilay@cs.wisc.edu void RingModulator::propagateTransitionInfo() 16610447Snilay@cs.wisc.edu { 16710447Snilay@cs.wisc.edu // Very simple...whatever comes in electrically is encoded optically 16810447Snilay@cs.wisc.edu getOpticalOutputPort("Out")->setTransitionInfo(getInputPort("In")->getTransitionInfo()); 16910447Snilay@cs.wisc.edu 17010447Snilay@cs.wisc.edu return; 17110447Snilay@cs.wisc.edu } 17210447Snilay@cs.wisc.edu 17310447Snilay@cs.wisc.edu void RingModulator::precomputeTech() 17410447Snilay@cs.wisc.edu { 17510447Snilay@cs.wisc.edu // Get parameters 17610447Snilay@cs.wisc.edu double data_rate = getParameter("DataRate"); 17710447Snilay@cs.wisc.edu 17810447Snilay@cs.wisc.edu // Constants shortcuts 17910447Snilay@cs.wisc.edu double pi = Constants::pi; 18010447Snilay@cs.wisc.edu double c = Constants::c; 18110447Snilay@cs.wisc.edu double k = Constants::k; 18210447Snilay@cs.wisc.edu double e0 = Constants::e0; 18310447Snilay@cs.wisc.edu double es = Constants::es; 18410447Snilay@cs.wisc.edu double q = Constants::q; 18510447Snilay@cs.wisc.edu double T = getTechModel()->get("Temperature"); 18610447Snilay@cs.wisc.edu 18710447Snilay@cs.wisc.edu // Get modulator parameters 18810447Snilay@cs.wisc.edu double lambda = getTechModel()->get("Ring->Lambda").toDouble(); 18910447Snilay@cs.wisc.edu double n_f = getTechModel()->get("Modulator->Ring->FCPDEffect").toDouble(); 19010447Snilay@cs.wisc.edu double NA = getTechModel()->get("Modulator->Ring->NA").toDouble(); 19110447Snilay@cs.wisc.edu double ND = getTechModel()->get("Modulator->Ring->ND").toDouble(); 19210447Snilay@cs.wisc.edu double ni = getTechModel()->get("Modulator->Ring->ni").toDouble(); 19310447Snilay@cs.wisc.edu double L_j = getTechModel()->get("Modulator->Ring->JunctionRatio").toDouble(); 19410447Snilay@cs.wisc.edu double H = getTechModel()->get("Modulator->Ring->Height").toDouble(); 19510447Snilay@cs.wisc.edu double W = getTechModel()->get("Modulator->Ring->Width").toDouble(); 19610447Snilay@cs.wisc.edu double g_c = getTechModel()->get("Modulator->Ring->ConfinementFactor").toDouble(); 19710447Snilay@cs.wisc.edu // Get ring parameters 19810447Snilay@cs.wisc.edu double R = getTechModel()->get("Ring->Radius").toDouble(); 19910447Snilay@cs.wisc.edu double n_g = getTechModel()->get("Ring->GroupIndex").toDouble(); 20010447Snilay@cs.wisc.edu double Q_max = getTechModel()->get("Ring->MaxQualityFactor").toDouble(); 20110447Snilay@cs.wisc.edu 20210447Snilay@cs.wisc.edu // Setup calculations 20310447Snilay@cs.wisc.edu double f0 = c / lambda; 20410447Snilay@cs.wisc.edu double BW = data_rate; // Modulator bandwidth 20510447Snilay@cs.wisc.edu double Q_f = std::min(f0 / BW, Q_max); // Quality factor 20610447Snilay@cs.wisc.edu double L_tot = 2 * pi * R; // Optical length of the ring 20710447Snilay@cs.wisc.edu 20810447Snilay@cs.wisc.edu double V_bi = k * T / q * log(NA * ND / (ni * ni)); // Junction Built-in voltage 20910447Snilay@cs.wisc.edu double x_d0 = sqrt(2 * e0 * es / q * V_bi * (NA + ND) / (NA * ND)); // Junction nominal depletion width 21010447Snilay@cs.wisc.edu double C_j0 = e0 * es * L_tot * L_j * W / x_d0; // Junction nominal cap 21110447Snilay@cs.wisc.edu double Q_0 = q * n_g * (L_tot * H * W) / (2 * n_f * Q_f * g_c); // Charge in depletion region 21210447Snilay@cs.wisc.edu 21310447Snilay@cs.wisc.edu // Store into precomputed values 21410447Snilay@cs.wisc.edu m_precompute_V_bi_ = V_bi; 21510447Snilay@cs.wisc.edu m_precompute_x_d0_ = x_d0; 21610447Snilay@cs.wisc.edu m_precompute_C_j0_ = C_j0; 21710447Snilay@cs.wisc.edu m_precompute_Q_0_ = Q_0; 21810447Snilay@cs.wisc.edu 21910447Snilay@cs.wisc.edu return; 22010447Snilay@cs.wisc.edu } 22110447Snilay@cs.wisc.edu 22210447Snilay@cs.wisc.edu bool RingModulator::designModulator(double IL_dB_, double ER_dB_) 22310447Snilay@cs.wisc.edu { 22410447Snilay@cs.wisc.edu // Get parameters 22510447Snilay@cs.wisc.edu double vdd = getTechModel()->get("Vdd"); 22610447Snilay@cs.wisc.edu double data_rate = getParameter("DataRate"); 22710447Snilay@cs.wisc.edu unsigned int max_predriver_stages = 20; //TODO: Make this not hardcoded 22810447Snilay@cs.wisc.edu // Get modulator parameters 22910447Snilay@cs.wisc.edu double boost_ratio = getTechModel()->get("Modulator->Ring->SupplyBoostRatio"); 23010447Snilay@cs.wisc.edu double Tn = getTechModel()->get("Modulator->Ring->Tn").toDouble();; 23110447Snilay@cs.wisc.edu double H = getTechModel()->get("Modulator->Ring->Height").toDouble(); 23210447Snilay@cs.wisc.edu 23310447Snilay@cs.wisc.edu // Get Gen properties 23410447Snilay@cs.wisc.edu int number_wavelengths = getGenProperties()->get("NumberWavelengths"); 23510447Snilay@cs.wisc.edu 23610447Snilay@cs.wisc.edu // Checking ASSERTions (input properties that don't make any sense) 23710447Snilay@cs.wisc.edu ASSERT(ER_dB_ > 0, "[Error] " + getInstanceName() + " -> Extinction ratio must be > 0!"); 23810447Snilay@cs.wisc.edu ASSERT(IL_dB_ > 0, "[Error] " + getInstanceName() + " -> Insertion loss must be > 0!"); 23910447Snilay@cs.wisc.edu 24010447Snilay@cs.wisc.edu // Setup calculations 24110447Snilay@cs.wisc.edu double ER = pow(10, ER_dB_ / 10); // Extinction ratio 24210447Snilay@cs.wisc.edu double T1 = pow(10, -IL_dB_ / 10); // Transmisivity on 24310447Snilay@cs.wisc.edu double T0 = T1 / ER; // Transmisivity off 24410447Snilay@cs.wisc.edu 24510447Snilay@cs.wisc.edu // Get precomputed values 24610447Snilay@cs.wisc.edu double V_bi = m_precompute_V_bi_; 24710447Snilay@cs.wisc.edu double x_d0 = m_precompute_x_d0_; 24810447Snilay@cs.wisc.edu double C_j0 = m_precompute_C_j0_; 24910447Snilay@cs.wisc.edu double Q_0 = m_precompute_Q_0_; 25010447Snilay@cs.wisc.edu 25110447Snilay@cs.wisc.edu // Charge 25210447Snilay@cs.wisc.edu double int_c = -2 * V_bi * C_j0; 25310447Snilay@cs.wisc.edu // Calculate shift using lorentzian 25410447Snilay@cs.wisc.edu double gamma = sqrt((1 - Tn)/(1 - T1) - 1) - sqrt((1 - Tn)/(1 - T0) - 1); // gamma = delta_f / delta_f_FWHM 25510447Snilay@cs.wisc.edu double Q = gamma * Q_0; // Charge required to hit given Tf 25610447Snilay@cs.wisc.edu // Voltage required 25710447Snilay@cs.wisc.edu double V_a = V_bi * (pow( (Q - int_c)/(2 * V_bi * C_j0), 2) - 1); 25810447Snilay@cs.wisc.edu // Calculate driver vdd 25910447Snilay@cs.wisc.edu double hvdd = V_a * boost_ratio; 26010447Snilay@cs.wisc.edu // Depletion region required 26110447Snilay@cs.wisc.edu double x_d = x_d0 * sqrt((V_bi + V_a) / V_bi); 26210447Snilay@cs.wisc.edu 26310447Snilay@cs.wisc.edu // Calculate C_eff 26410447Snilay@cs.wisc.edu double c_eff = Q / V_a; 26510447Snilay@cs.wisc.edu 26610447Snilay@cs.wisc.edu // Feasibility checks 26710447Snilay@cs.wisc.edu // Not feasible if the transmisivity when transmitting an optical 1 is greater than 1.0... 26810447Snilay@cs.wisc.edu if (T1 >= 1) return false; 26910447Snilay@cs.wisc.edu // Not feasible if the transmisivity when transmitting an optical 0 is smaller than the notch of the ring 27010447Snilay@cs.wisc.edu if (T0 <= Tn) return false; 27110447Snilay@cs.wisc.edu // Not feasible if the extinction ratio is greater than the notch of the ring 27210447Snilay@cs.wisc.edu if (ER >= 1 / Tn) return false; 27310447Snilay@cs.wisc.edu // Not feasible if the required depletion width is greater than the height of the junction 27410447Snilay@cs.wisc.edu if (x_d >= H) return false; 27510447Snilay@cs.wisc.edu 27610447Snilay@cs.wisc.edu // Analytically calculate driver sizes 27710447Snilay@cs.wisc.edu // Get parameters corresponding to a unit-inverter 27810447Snilay@cs.wisc.edu double unit_c_g = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Cap->A"); 27910447Snilay@cs.wisc.edu double unit_c_d = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Cap->Y"); 28010447Snilay@cs.wisc.edu double unit_r_o = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->DriveRes->Y"); 28110447Snilay@cs.wisc.edu double unit_area_active = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Area->Active"); 28210447Snilay@cs.wisc.edu double unit_area_metal1 = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Area->Metal1Wire"); 28310447Snilay@cs.wisc.edu 28410447Snilay@cs.wisc.edu // Get device resistance/cap 28510447Snilay@cs.wisc.edu double device_par_res = getTechModel()->get("Modulator->Ring->ParasiticRes"); 28610447Snilay@cs.wisc.edu double device_par_cap = getTechModel()->get("Modulator->Ring->ParasiticCap"); 28710447Snilay@cs.wisc.edu 28810447Snilay@cs.wisc.edu // Use timing tree to size modulator drivers 28910447Snilay@cs.wisc.edu // Coefficient of R*C to give a 0->V_a transition 29010447Snilay@cs.wisc.edu double transition_scale = log(hvdd / (hvdd - V_a)); 29110447Snilay@cs.wisc.edu double transition_required = 1 / (4 * data_rate); // I am not sure what the factor of 4 is for... 29210447Snilay@cs.wisc.edu 29310447Snilay@cs.wisc.edu // Calculate inverter intrinsic transition time 29410447Snilay@cs.wisc.edu double transition_intrinsic = transition_scale * unit_c_d * unit_r_o; 29510447Snilay@cs.wisc.edu // Calculate minimum possible device transition time 29610447Snilay@cs.wisc.edu double min_transition_intrinsic = transition_intrinsic + transition_scale * device_par_res * c_eff; 29710447Snilay@cs.wisc.edu // If the minimum possible transition time is already bigger 29810447Snilay@cs.wisc.edu // than the required transition, then this particular driver is not possible... 29910447Snilay@cs.wisc.edu if (min_transition_intrinsic > transition_required) 30010447Snilay@cs.wisc.edu return false; 30110447Snilay@cs.wisc.edu 30210447Snilay@cs.wisc.edu // Calculate driver size 30310447Snilay@cs.wisc.edu double driver_size = max(1.0, transition_scale * unit_r_o * (c_eff + device_par_cap) / (transition_required - min_transition_intrinsic)); 30410447Snilay@cs.wisc.edu // Keep track of the total multiplier of unit inverters (for area, leakage calculations) 30510447Snilay@cs.wisc.edu double total_unit_inverters = driver_size * max(1.0, hvdd / vdd); 30610447Snilay@cs.wisc.edu // Calculate load cap for predriver stages 30710447Snilay@cs.wisc.edu double current_load_cap = driver_size * unit_c_g; 30810447Snilay@cs.wisc.edu // Number of predriver stages 30910447Snilay@cs.wisc.edu unsigned int predriver_stages = 0; 31010447Snilay@cs.wisc.edu // Add predriver stages until the input cap is less than the unit INV_X1 gate cap or 31110447Snilay@cs.wisc.edu // if the signal is still inverted (need an odd number of predriver stages) 31210447Snilay@cs.wisc.edu while (current_load_cap > unit_c_g || (predriver_stages == 0) || ((predriver_stages & 0x1) == 0)) 31310447Snilay@cs.wisc.edu { 31410447Snilay@cs.wisc.edu // Calculate the size of the current predriver stage 31510447Snilay@cs.wisc.edu double current_predriver_size = max(1.0, unit_r_o * current_load_cap / (transition_required - transition_intrinsic)); 31610447Snilay@cs.wisc.edu // Calculate load cap for the next predriver stage 31710447Snilay@cs.wisc.edu current_load_cap = current_predriver_size * unit_c_g; 31810447Snilay@cs.wisc.edu // Add cap to total predriver total cap 31910447Snilay@cs.wisc.edu total_unit_inverters += current_predriver_size; 32010447Snilay@cs.wisc.edu // Consider this a failure if the number of predriver stages exceed some maximum 32110447Snilay@cs.wisc.edu if (predriver_stages > max_predriver_stages) 32210447Snilay@cs.wisc.edu return false; 32310447Snilay@cs.wisc.edu 32410447Snilay@cs.wisc.edu ++predriver_stages; 32510447Snilay@cs.wisc.edu } 32610447Snilay@cs.wisc.edu // Set the input load capacitance 32710447Snilay@cs.wisc.edu getLoad("PredriverCap")->setLoadCap(current_load_cap); 32810447Snilay@cs.wisc.edu 32910447Snilay@cs.wisc.edu // Set generated properties 33010447Snilay@cs.wisc.edu getGenProperties()->set("DriverSize", driver_size); 33110447Snilay@cs.wisc.edu getGenProperties()->set("FirstPredriverSize", current_load_cap); 33210447Snilay@cs.wisc.edu getGenProperties()->set("TotalPredriverSize", total_unit_inverters - driver_size); 33310447Snilay@cs.wisc.edu getGenProperties()->set("Hvdd", hvdd); 33410447Snilay@cs.wisc.edu getGenProperties()->set("Ceff", c_eff); 33510447Snilay@cs.wisc.edu 33610447Snilay@cs.wisc.edu // Calculate leakage, area, energy consumption 33710447Snilay@cs.wisc.edu double area_active = total_unit_inverters * unit_area_active; 33810447Snilay@cs.wisc.edu double area_metal1 = total_unit_inverters * unit_area_metal1; 33910447Snilay@cs.wisc.edu 34010447Snilay@cs.wisc.edu // Set results 34110447Snilay@cs.wisc.edu getAreaResult("Active")->setValue(area_active * number_wavelengths); 34210447Snilay@cs.wisc.edu getAreaResult("Metal1Wire")->setValue(area_metal1 * number_wavelengths); 34310447Snilay@cs.wisc.edu 34410447Snilay@cs.wisc.edu // Only if everything was successful do we set the modulator specification 34510447Snilay@cs.wisc.edu getModulator("RingModulator")->setLosses(IL_dB_, ER_dB_); 34610447Snilay@cs.wisc.edu return true; 34710447Snilay@cs.wisc.edu } 34810447Snilay@cs.wisc.edu 34910447Snilay@cs.wisc.edu double RingModulator::calcModulatorEnergy() const 35010447Snilay@cs.wisc.edu { 35110447Snilay@cs.wisc.edu // Get tech parameters 35210447Snilay@cs.wisc.edu double vdd = getTechModel()->get("Vdd"); 35310447Snilay@cs.wisc.edu double device_par_cap = getTechModel()->get("Modulator->Ring->ParasiticCap"); 35410447Snilay@cs.wisc.edu 35510447Snilay@cs.wisc.edu // Get Gen properties 35610447Snilay@cs.wisc.edu int number_wavelengths = getGenProperties()->get("NumberWavelengths"); 35710447Snilay@cs.wisc.edu 35810447Snilay@cs.wisc.edu bool success = getGenProperties()->get("Success"); 35910447Snilay@cs.wisc.edu if (success) 36010447Snilay@cs.wisc.edu { 36110447Snilay@cs.wisc.edu double driver_size = getGenProperties()->get("DriverSize"); 36210447Snilay@cs.wisc.edu double total_predriver_size = getGenProperties()->get("TotalPredriverSize"); 36310447Snilay@cs.wisc.edu double first_predriver_size = getGenProperties()->get("FirstPredriverSize"); 36410447Snilay@cs.wisc.edu double c_eff = getGenProperties()->get("Ceff"); 36510447Snilay@cs.wisc.edu double hvdd = getGenProperties()->get("Hvdd"); 36610447Snilay@cs.wisc.edu 36710447Snilay@cs.wisc.edu // Get parameters corresponding to a unit-inverter 36810447Snilay@cs.wisc.edu double unit_c_g = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Cap->A"); 36910447Snilay@cs.wisc.edu double unit_c_d = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Cap->Y"); 37010447Snilay@cs.wisc.edu 37110447Snilay@cs.wisc.edu // Approximate leakage 37210447Snilay@cs.wisc.edu double energy_predriver = number_wavelengths * vdd * vdd * ((unit_c_d * total_predriver_size + 37310447Snilay@cs.wisc.edu unit_c_g * (total_predriver_size + driver_size - first_predriver_size))); 37410447Snilay@cs.wisc.edu double energy_driver = number_wavelengths * hvdd * std::max(hvdd, vdd) * (driver_size * unit_c_d + c_eff + device_par_cap); 37510447Snilay@cs.wisc.edu 37610447Snilay@cs.wisc.edu return (energy_predriver + energy_driver); 37710447Snilay@cs.wisc.edu } 37810447Snilay@cs.wisc.edu else 37910447Snilay@cs.wisc.edu return 1e99; // An infinitely expensive modulator 38010447Snilay@cs.wisc.edu } 38110447Snilay@cs.wisc.edu 38210447Snilay@cs.wisc.edu bool RingModulator::setTransmitterSpec(double IL_dB_, double ER_dB_) 38310447Snilay@cs.wisc.edu { 38410447Snilay@cs.wisc.edu setProperty("InsertionLoss", IL_dB_); 38510447Snilay@cs.wisc.edu setProperty("ExtinctionRatio", ER_dB_); 38610447Snilay@cs.wisc.edu update(); 38710447Snilay@cs.wisc.edu evaluate(); 38810447Snilay@cs.wisc.edu 38910447Snilay@cs.wisc.edu return getGenProperties()->get("Success"); 39010447Snilay@cs.wisc.edu } 39110447Snilay@cs.wisc.edu 39210447Snilay@cs.wisc.edu double RingModulator::getPower(double util_) const 39310447Snilay@cs.wisc.edu { 39410447Snilay@cs.wisc.edu // Get parameters 39510447Snilay@cs.wisc.edu double data_rate = getParameter("DataRate"); 39610447Snilay@cs.wisc.edu // Check arguments 39710447Snilay@cs.wisc.edu ASSERT((util_ <= 1.0) && (util_ >= 0.0), "[Error] " + getInstanceName() + " -> Modulator utilization must be between 0.0 and 1.0!"); 39810447Snilay@cs.wisc.edu 39910447Snilay@cs.wisc.edu return calcModulatorEnergy() * 0.25 * util_ * data_rate; 40010447Snilay@cs.wisc.edu } 40110447Snilay@cs.wisc.edu 40210447Snilay@cs.wisc.edu} // namespace DSENT 40310447Snilay@cs.wisc.edu 404