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