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