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/RingDetector.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/OpticalDetector.h" 3410447Snilay@cs.wisc.edu#include "model/optical_graph/OpticalFilter.h" 3510447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalDriver.h" 3610447Snilay@cs.wisc.edu#include "model/timing_graph/ElectricalNet.h" 3710447Snilay@cs.wisc.edu 3810447Snilay@cs.wisc.edunamespace DSENT 3910447Snilay@cs.wisc.edu{ 4010447Snilay@cs.wisc.edu // TODOs for this model 4110447Snilay@cs.wisc.edu // Add the other receiver topologies from [Georgas, CICC 2011] 4210447Snilay@cs.wisc.edu // Split integ_time_ratio = SA integ time ratio 4310447Snilay@cs.wisc.edu // Right now perfect clock gating is assumed...may not be what we want 4410447Snilay@cs.wisc.edu 4510447Snilay@cs.wisc.edu // Constants 4610447Snilay@cs.wisc.edu const String RingDetector::INTEGRATINGSENSEAMP = "INTSA"; 4710447Snilay@cs.wisc.edu 4810447Snilay@cs.wisc.edu RingDetector::RingDetector(const String& instance_name_, const TechModel* tech_model_) 4910447Snilay@cs.wisc.edu : OpticalModel(instance_name_, tech_model_), OpticalReceiver() 5010447Snilay@cs.wisc.edu { 5110447Snilay@cs.wisc.edu initParameters(); 5210447Snilay@cs.wisc.edu initProperties(); 5310447Snilay@cs.wisc.edu } 5410447Snilay@cs.wisc.edu 5510447Snilay@cs.wisc.edu RingDetector::~RingDetector() 5610447Snilay@cs.wisc.edu {} 5710447Snilay@cs.wisc.edu 5810447Snilay@cs.wisc.edu void RingDetector::initParameters() 5910447Snilay@cs.wisc.edu { 6010447Snilay@cs.wisc.edu addParameterName("DataRate"); 6110447Snilay@cs.wisc.edu addParameterName("InStart"); 6210447Snilay@cs.wisc.edu addParameterName("InEnd"); 6310447Snilay@cs.wisc.edu addParameterName("DetStart"); 6410447Snilay@cs.wisc.edu addParameterName("DetEnd"); 6510447Snilay@cs.wisc.edu addParameterName("DropAll"); 6610447Snilay@cs.wisc.edu addParameterName("Topology"); 6710447Snilay@cs.wisc.edu return; 6810447Snilay@cs.wisc.edu } 6910447Snilay@cs.wisc.edu 7010447Snilay@cs.wisc.edu void RingDetector::initProperties() 7110447Snilay@cs.wisc.edu { 7210447Snilay@cs.wisc.edu return; 7310447Snilay@cs.wisc.edu } 7410447Snilay@cs.wisc.edu 7510447Snilay@cs.wisc.edu void RingDetector::constructModel() 7610447Snilay@cs.wisc.edu { 7710447Snilay@cs.wisc.edu // Get parameters 7810447Snilay@cs.wisc.edu WavelengthGroup in_wavelengths = makeWavelengthGroup(getParameter("InStart"), getParameter("InEnd")); 7910447Snilay@cs.wisc.edu WavelengthGroup det_wavelengths = makeWavelengthGroup(getParameter("DetStart"), getParameter("DetEnd")); 8010447Snilay@cs.wisc.edu int number_wavelengths = det_wavelengths.second - det_wavelengths.first + 1; 8110447Snilay@cs.wisc.edu bool drop_all = getParameter("DropAll"); 8210447Snilay@cs.wisc.edu const String& topology = getParameter("Topology"); 8310447Snilay@cs.wisc.edu 8410447Snilay@cs.wisc.edu // Set some generated properties 8510447Snilay@cs.wisc.edu getGenProperties()->set("NumberWavelengths", number_wavelengths); 8610447Snilay@cs.wisc.edu 8710447Snilay@cs.wisc.edu // Create device area result 8810447Snilay@cs.wisc.edu addAreaResult(new AtomicResult("Photonic")); 8910447Snilay@cs.wisc.edu // Create electrical results 9010447Snilay@cs.wisc.edu createElectricalAtomicResults(); 9110447Snilay@cs.wisc.edu if (topology == INTEGRATINGSENSEAMP) addEventResult(new AtomicResult("Receive")); 9210447Snilay@cs.wisc.edu else ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown receiver topology (" + topology + ")!"); 9310447Snilay@cs.wisc.edu 9410447Snilay@cs.wisc.edu // Create optical ports 9510447Snilay@cs.wisc.edu createOpticalInputPort( "In", in_wavelengths); 9610447Snilay@cs.wisc.edu createOpticalOutputPort( "Out", in_wavelengths); 9710447Snilay@cs.wisc.edu // Create the filter and modulator 9810447Snilay@cs.wisc.edu createFilter( "RingFilter", in_wavelengths, drop_all, det_wavelengths); 9910447Snilay@cs.wisc.edu createDetector( "RingDetector", det_wavelengths, this); 10010447Snilay@cs.wisc.edu OpticalFilter* ring_filter = getFilter("RingFilter"); 10110447Snilay@cs.wisc.edu OpticalDetector* ring_detector = getDetector("RingDetector"); 10210447Snilay@cs.wisc.edu // Connect the filter and modulator 10310447Snilay@cs.wisc.edu getWaveguide("In")->addDownstreamNode(ring_filter); 10410447Snilay@cs.wisc.edu ring_filter->addDownstreamNode(getWaveguide("Out")); 10510447Snilay@cs.wisc.edu ring_filter->setDropPort(ring_detector); 10610447Snilay@cs.wisc.edu 10710447Snilay@cs.wisc.edu // Create electrical ports 10810447Snilay@cs.wisc.edu createOutputPort("Out", makeNetIndex(0, number_wavelengths-1)); 10910447Snilay@cs.wisc.edu // Create net 11010447Snilay@cs.wisc.edu createNet("OutVFO"); 11110447Snilay@cs.wisc.edu // Create output driver 11210447Snilay@cs.wisc.edu createDriver("OutDriver", false); 11310447Snilay@cs.wisc.edu // Connect driver 11410447Snilay@cs.wisc.edu getDriver("OutDriver")->addDownstreamNode(getNet("OutVFO")); 11510447Snilay@cs.wisc.edu // Connect output 11610447Snilay@cs.wisc.edu assignVirtualFanout("Out", "OutVFO"); 11710447Snilay@cs.wisc.edu 11810447Snilay@cs.wisc.edu // Precompute some technology values 11910447Snilay@cs.wisc.edu precomputeTech(); 12010447Snilay@cs.wisc.edu 12110447Snilay@cs.wisc.edu return; 12210447Snilay@cs.wisc.edu } 12310447Snilay@cs.wisc.edu 12410447Snilay@cs.wisc.edu void RingDetector::updateModel() 12510447Snilay@cs.wisc.edu { 12610447Snilay@cs.wisc.edu // Get some generated properties 12710447Snilay@cs.wisc.edu unsigned int number_wavelengths = getGenProperties()->get("NumberWavelengths"); 12810447Snilay@cs.wisc.edu 12910447Snilay@cs.wisc.edu // Get tech model numbers 13010447Snilay@cs.wisc.edu double ring_area = getTechModel()->get("Ring->Area"); 13110447Snilay@cs.wisc.edu double thru_loss = getTechModel()->get("Ring->ThroughLoss"); 13210447Snilay@cs.wisc.edu double drop_loss = getTechModel()->get("Ring->DropLoss"); 13310447Snilay@cs.wisc.edu double pd_loss = getTechModel()->get("Photodetector->Loss"); 13410447Snilay@cs.wisc.edu double pd_responsivity = getTechModel()->get("Photodetector->Responsivity"); 13510447Snilay@cs.wisc.edu 13610447Snilay@cs.wisc.edu // Design the receiver 13710447Snilay@cs.wisc.edu designReceiver(); 13810447Snilay@cs.wisc.edu 13910447Snilay@cs.wisc.edu // Update losses 14010447Snilay@cs.wisc.edu // Connect the filter and modulator 14110447Snilay@cs.wisc.edu OpticalFilter* ring_filter = getFilter("RingFilter"); 14210447Snilay@cs.wisc.edu OpticalDetector* ring_detector = getDetector("RingDetector"); 14310447Snilay@cs.wisc.edu ring_filter->setLoss(thru_loss * number_wavelengths); 14410447Snilay@cs.wisc.edu ring_filter->setDropLoss(drop_loss + thru_loss * number_wavelengths); 14510447Snilay@cs.wisc.edu ring_detector->setLoss(pd_loss); 14610447Snilay@cs.wisc.edu ring_detector->setResponsivity(pd_responsivity); 14710447Snilay@cs.wisc.edu // Update device area 14810447Snilay@cs.wisc.edu getAreaResult("Photonic")->setValue(ring_area * (number_wavelengths)); 14910447Snilay@cs.wisc.edu 15010447Snilay@cs.wisc.edu return; 15110447Snilay@cs.wisc.edu } 15210447Snilay@cs.wisc.edu 15310447Snilay@cs.wisc.edu void RingDetector::useModel() 15410447Snilay@cs.wisc.edu { 15510447Snilay@cs.wisc.edu // Get parameters 15610447Snilay@cs.wisc.edu const String& topology = getParameter("Topology"); 15710447Snilay@cs.wisc.edu 15810447Snilay@cs.wisc.edu // Get some generated properties 15910447Snilay@cs.wisc.edu unsigned int number_wavelengths = getGenProperties()->get("NumberWavelengths"); 16010447Snilay@cs.wisc.edu 16110447Snilay@cs.wisc.edu // Get optical input transition info 16210447Snilay@cs.wisc.edu const TransitionInfo& in_trans = getOpticalInputPort("In")->getTransitionInfo(); 16310447Snilay@cs.wisc.edu 16410447Snilay@cs.wisc.edu // Get tech models 16510447Snilay@cs.wisc.edu double vdd = getTechModel()->get("Vdd"); 16610447Snilay@cs.wisc.edu // Get caps 16710447Snilay@cs.wisc.edu double unit_gate_cap = getTechModel()->get("Gate->MinWidth").toDouble() * getTechModel()->get("Gate->CapPerWidth").toDouble(); 16810447Snilay@cs.wisc.edu double unit_drain_cap = getTechModel()->get("Gate->MinWidth").toDouble() * getTechModel()->get("Drain->CapPerWidth").toDouble(); 16910447Snilay@cs.wisc.edu double inv_x1_gate_cap = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Cap->A"); 17010447Snilay@cs.wisc.edu double inv_x1_drain_cap = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Cap->Y"); 17110447Snilay@cs.wisc.edu 17210447Snilay@cs.wisc.edu // Construct a simple sense-amp model 17310447Snilay@cs.wisc.edu if(topology == INTEGRATINGSENSEAMP) 17410447Snilay@cs.wisc.edu { 17510447Snilay@cs.wisc.edu // Use ratios from the receiver published in [Georgas, ESSCIRC 2011] 17610447Snilay@cs.wisc.edu // Note: 17710447Snilay@cs.wisc.edu // The numbers in the paper (43fJ/b, 50 fJ/b in the cited work) is done with the clock buffer (there are 4 receivers), 17810447Snilay@cs.wisc.edu // capacitive DAC, and extra output flops used in the physical layout, as the compared receiver is extremely conservative 17910447Snilay@cs.wisc.edu // We simplified this model to not have the capacitive DAC, the clock buffer (since this is an individual receiver), or 18010447Snilay@cs.wisc.edu // the extra output flops (since receiver structure is already a posedge flop functionally). 18110447Snilay@cs.wisc.edu // Look for an upcoming paper [Georgas, JSSC 2012] (when it is published) for the power breakdown pie-chart for the receiver. 18210447Snilay@cs.wisc.edu // This model only models the latch (sampler) and the dynamic to static (RS latch) part of the design, which is all you really 18310447Snilay@cs.wisc.edu // need in the receiver. 18410447Snilay@cs.wisc.edu 18510447Snilay@cs.wisc.edu // Gate caps 18610447Snilay@cs.wisc.edu double c_gate_sampler = unit_gate_cap * (4 * 2.0 + 2 * 1.0 + 2 * 3.0 + 2 * 5.0) + unit_gate_cap * (2 * 6.0 + 2 * 1.0) + inv_x1_gate_cap; 18710447Snilay@cs.wisc.edu double c_gate_rslatch = unit_gate_cap * (4 * 1.0) + inv_x1_gate_cap; 18810447Snilay@cs.wisc.edu // Drain caps 18910447Snilay@cs.wisc.edu double c_drain_sampler = unit_drain_cap * (2 * 2.0 + 2 * 1.0 + 3 * 5.0 + 1 * 3.0) + inv_x1_drain_cap; 19010447Snilay@cs.wisc.edu double c_drain_rslatch = unit_drain_cap * (2 * 6.0) + inv_x1_drain_cap; 19110447Snilay@cs.wisc.edu // Sum up cap switched for the sampler 19210447Snilay@cs.wisc.edu double c_sampler = c_gate_sampler + c_drain_sampler; 19310447Snilay@cs.wisc.edu double c_rslatch = c_gate_rslatch + c_drain_rslatch; 19410447Snilay@cs.wisc.edu // Average cap switched 19510447Snilay@cs.wisc.edu // Sampler is differential, one side will always switch (R or S in the latch) regardless of probability 19610447Snilay@cs.wisc.edu double avg_cap = c_sampler + c_rslatch * in_trans.getProbability0() * in_trans.getProbability1(); 19710447Snilay@cs.wisc.edu 19810447Snilay@cs.wisc.edu // Get parameters corresponding to a unit-inverter 19910447Snilay@cs.wisc.edu double unit_leak_0 = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Leakage->!A"); 20010447Snilay@cs.wisc.edu double unit_leak_1 = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Leakage->A"); 20110447Snilay@cs.wisc.edu 20210447Snilay@cs.wisc.edu // Approximate leakage (curve fit with design) 20310447Snilay@cs.wisc.edu double total_leakage = 0.5 * (unit_leak_0 + unit_leak_1) * 7.43; 20410447Snilay@cs.wisc.edu 20510447Snilay@cs.wisc.edu // Create results 20610447Snilay@cs.wisc.edu getEventResult("Receive")->setValue(vdd * vdd * avg_cap * number_wavelengths); 20710447Snilay@cs.wisc.edu getNddPowerResult("Leakage")->setValue(total_leakage * number_wavelengths); 20810447Snilay@cs.wisc.edu 20910447Snilay@cs.wisc.edu } 21010447Snilay@cs.wisc.edu else ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown receiver topology (" + topology + ")!"); 21110447Snilay@cs.wisc.edu 21210447Snilay@cs.wisc.edu return; 21310447Snilay@cs.wisc.edu } 21410447Snilay@cs.wisc.edu 21510447Snilay@cs.wisc.edu void RingDetector::propagateTransitionInfo() 21610447Snilay@cs.wisc.edu { 21710447Snilay@cs.wisc.edu // Propagate probabilities from optical input to electrical output port 21810447Snilay@cs.wisc.edu getOutputPort("Out")->setTransitionInfo(getOpticalInputPort("In")->getTransitionInfo()); 21910447Snilay@cs.wisc.edu 22010447Snilay@cs.wisc.edu return; 22110447Snilay@cs.wisc.edu } 22210447Snilay@cs.wisc.edu 22310447Snilay@cs.wisc.edu void RingDetector::precomputeTech() 22410447Snilay@cs.wisc.edu { 22510447Snilay@cs.wisc.edu // Get parameters 22610447Snilay@cs.wisc.edu const double data_rate = getParameter("DataRate"); 22710447Snilay@cs.wisc.edu const String& topology = getParameter("Topology"); 22810447Snilay@cs.wisc.edu 22910447Snilay@cs.wisc.edu // Get tech model numbers 23010447Snilay@cs.wisc.edu double pd_cap = getTechModel()->get("Photodetector->Cap"); 23110447Snilay@cs.wisc.edu double parasitic_cap = getTechModel()->get("Photodetector->ParasiticCap"); 23210447Snilay@cs.wisc.edu double apd = getTechModel()->get("Photodetector->AvalancheGain"); 23310447Snilay@cs.wisc.edu double vdd = getTechModel()->get("Vdd"); 23410447Snilay@cs.wisc.edu 23510447Snilay@cs.wisc.edu // Constants shortcuts 23610447Snilay@cs.wisc.edu double pi = Constants::pi; 23710447Snilay@cs.wisc.edu double k = Constants::k; 23810447Snilay@cs.wisc.edu double q = Constants::q; 23910447Snilay@cs.wisc.edu double T = getTechModel()->get("Temperature"); 24010447Snilay@cs.wisc.edu 24110447Snilay@cs.wisc.edu if(topology == INTEGRATINGSENSEAMP) 24210447Snilay@cs.wisc.edu { 24310447Snilay@cs.wisc.edu // Get more tech parameters 24410447Snilay@cs.wisc.edu double integ_time_ratio = getTechModel()->get("Receiver->Int->IntegrationTimeRatio"); 24510447Snilay@cs.wisc.edu double BER = getTechModel()->get("SenseAmp->BER"); 24610447Snilay@cs.wisc.edu double CMRR = getTechModel()->get("SenseAmp->CMRR"); 24710447Snilay@cs.wisc.edu double offset_comp_bits = getTechModel()->get("SenseAmp->OffsetCompensationBits"); 24810447Snilay@cs.wisc.edu double offset = getTechModel()->get("SenseAmp->OffsetRatio").toDouble() * vdd; 24910447Snilay@cs.wisc.edu double supply_noise_rand = getTechModel()->get("SenseAmp->SupplyNoiseRandRatio").toDouble() * vdd; 25010447Snilay@cs.wisc.edu double supply_noise_det = getTechModel()->get("SenseAmp->SupplyNoiseDetRatio").toDouble() * vdd; 25110447Snilay@cs.wisc.edu double noise_margin = getTechModel()->get("SenseAmp->NoiseMargin"); 25210447Snilay@cs.wisc.edu double jitter_ratio = getTechModel()->get("SenseAmp->JitterRatio"); 25310447Snilay@cs.wisc.edu 25410447Snilay@cs.wisc.edu // Approximate tao using FO4 25510447Snilay@cs.wisc.edu double unit_drain_cap = getTechModel()->get("Gate->MinWidth").toDouble() * getTechModel()->get("Drain->CapPerWidth").toDouble(); 25610447Snilay@cs.wisc.edu double c_g = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Cap->A"); 25710447Snilay@cs.wisc.edu double c_d = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Cap->Y"); 25810447Snilay@cs.wisc.edu double r_o = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->DriveRes->Y"); 25910447Snilay@cs.wisc.edu // Calculate sense amp tau from sense amp output loading 26010447Snilay@cs.wisc.edu double tau = r_o * (c_g + c_d); 26110447Snilay@cs.wisc.edu // Set output inverter drive strength 26210447Snilay@cs.wisc.edu getDriver("OutDriver")->setOutputRes(r_o); 26310447Snilay@cs.wisc.edu 26410447Snilay@cs.wisc.edu // Calculate sense amp input cap based on schematic 26510447Snilay@cs.wisc.edu double sense_amp_cap_in = unit_drain_cap * (2.0 + 3.0 + 5.0 + 1.0); 26610447Snilay@cs.wisc.edu 26710447Snilay@cs.wisc.edu // Residual offset 26810447Snilay@cs.wisc.edu double v_residual = 3 * offset / pow(2, offset_comp_bits); 26910447Snilay@cs.wisc.edu // Noise 27010447Snilay@cs.wisc.edu double v_noise = supply_noise_rand * supply_noise_rand / (CMRR * CMRR); 27110447Snilay@cs.wisc.edu // Sense amp voltage build-up minimum 27210447Snilay@cs.wisc.edu double v_sense = vdd * exp(-(1 - integ_time_ratio) / (data_rate * tau)) + noise_margin + v_residual + supply_noise_det / CMRR; 27310447Snilay@cs.wisc.edu // Sigmas corresponding to BER 27410447Snilay@cs.wisc.edu double sigma = calcInvNormCdf(BER); 27510447Snilay@cs.wisc.edu 27610447Snilay@cs.wisc.edu //K_int is the time the bit is valid for evaluation 27710447Snilay@cs.wisc.edu 27810447Snilay@cs.wisc.edu // Total input cap load 27910447Snilay@cs.wisc.edu double input_node_cap = sense_amp_cap_in + pd_cap + parasitic_cap; 28010447Snilay@cs.wisc.edu double z_int = integ_time_ratio / (data_rate * input_node_cap); //should use K_int 28110447Snilay@cs.wisc.edu 28210447Snilay@cs.wisc.edu // Store precalculated values 28310447Snilay@cs.wisc.edu m_quad_a_ = 1 - (sigma * sigma * jitter_ratio * jitter_ratio); 28410447Snilay@cs.wisc.edu m_quad_b1_ = - 2 * pi / 2 * sigma * sigma * q * 0.7 * data_rate; 28510447Snilay@cs.wisc.edu m_quad_b2_ = -2 * v_sense / (z_int * apd); 28610447Snilay@cs.wisc.edu m_quad_c_ = 1 / (z_int * z_int) * (v_sense * v_sense - sigma * sigma * (k * T / input_node_cap + v_noise)); 28710447Snilay@cs.wisc.edu } 28810447Snilay@cs.wisc.edu else ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown receiver topology (" + topology + ")!"); 28910447Snilay@cs.wisc.edu 29010447Snilay@cs.wisc.edu return; 29110447Snilay@cs.wisc.edu } 29210447Snilay@cs.wisc.edu 29310447Snilay@cs.wisc.edu void RingDetector::designReceiver() 29410447Snilay@cs.wisc.edu { 29510447Snilay@cs.wisc.edu // Get some generated properties 29610447Snilay@cs.wisc.edu unsigned int number_wavelengths = getGenProperties()->get("NumberWavelengths"); 29710447Snilay@cs.wisc.edu 29810447Snilay@cs.wisc.edu // Get relevant properties/parameters 29910447Snilay@cs.wisc.edu const String& topology = getParameter("Topology"); 30010447Snilay@cs.wisc.edu 30110447Snilay@cs.wisc.edu // Construct a simple sense-amp model 30210447Snilay@cs.wisc.edu if(topology == INTEGRATINGSENSEAMP) 30310447Snilay@cs.wisc.edu { 30410447Snilay@cs.wisc.edu // No really good way to estimate the area...can assume each receiver is the size of 40 inverters, which is 30510447Snilay@cs.wisc.edu // about the right size for just the sense amp in the layout 30610447Snilay@cs.wisc.edu double unit_area_active = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Area->Active"); 30710447Snilay@cs.wisc.edu double unit_area_metal1 = getTechModel()->getStdCellLib()->getStdCellCache()->get("INV_X1->Area->Metal1Wire"); 30810447Snilay@cs.wisc.edu getAreaResult("Active")->setValue(unit_area_active * 40 * number_wavelengths); 30910447Snilay@cs.wisc.edu getAreaResult("Metal1Wire")->setValue(unit_area_metal1 * 40 * number_wavelengths); 31010447Snilay@cs.wisc.edu } 31110447Snilay@cs.wisc.edu else ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown receiver topology (" + topology + ")!"); 31210447Snilay@cs.wisc.edu 31310447Snilay@cs.wisc.edu return; 31410447Snilay@cs.wisc.edu } 31510447Snilay@cs.wisc.edu 31610447Snilay@cs.wisc.edu double RingDetector::getSensitivity(double ER_dB_) const 31710447Snilay@cs.wisc.edu { 31810447Snilay@cs.wisc.edu // Get parameters 31910447Snilay@cs.wisc.edu const String& topology = getParameter("Topology"); 32010447Snilay@cs.wisc.edu // Turn extinction ratio into a ratio from dB scale 32110447Snilay@cs.wisc.edu double ER = pow(10, ER_dB_ / 10); 32210447Snilay@cs.wisc.edu 32310447Snilay@cs.wisc.edu // Initialize sensitivity 32410447Snilay@cs.wisc.edu double sensitivity = 1e99; 32510447Snilay@cs.wisc.edu // Construct a simple sense-amp model 32610447Snilay@cs.wisc.edu if(topology == INTEGRATINGSENSEAMP) 32710447Snilay@cs.wisc.edu { 32810447Snilay@cs.wisc.edu // Scale photodetector shot noise using ER, add rest of noise source 32910447Snilay@cs.wisc.edu double b = m_quad_b1_ * (1 + ER) / (2 * (ER - 1)) + m_quad_b2_; 33010447Snilay@cs.wisc.edu 33110447Snilay@cs.wisc.edu // Find sensitivity (-b + sqrt(b^2-4ac)) / 2a 33210447Snilay@cs.wisc.edu sensitivity = ((-b + sqrt(b * b - 4 * m_quad_a_ * m_quad_c_)) / (2 * m_quad_a_)); 33310447Snilay@cs.wisc.edu } 33410447Snilay@cs.wisc.edu else ASSERT(false, "[Error] " + getInstanceName() + " -> Unknown receiver topology (" + topology + ")!"); 33510447Snilay@cs.wisc.edu 33610447Snilay@cs.wisc.edu return sensitivity; 33710447Snilay@cs.wisc.edu } 33810447Snilay@cs.wisc.edu 33910447Snilay@cs.wisc.edu double RingDetector::calcInvNormCdf(double num_) 34010447Snilay@cs.wisc.edu { 34110447Snilay@cs.wisc.edu // 53 bit precision for double FP 34210447Snilay@cs.wisc.edu unsigned int num_iterations = 20; 34310447Snilay@cs.wisc.edu // Upperbound the step 34410447Snilay@cs.wisc.edu double step = 20; 34510447Snilay@cs.wisc.edu double out = step; 34610447Snilay@cs.wisc.edu // Iteratively guess and check calculation 34710447Snilay@cs.wisc.edu for (unsigned int i = 0; i < num_iterations; ++i) 34810447Snilay@cs.wisc.edu { 34910447Snilay@cs.wisc.edu double current = 0.5 * erfc(out / sqrt(2)); 35010447Snilay@cs.wisc.edu if (current > num_) out += step; 35110447Snilay@cs.wisc.edu else out -= step; 35210447Snilay@cs.wisc.edu step = step * 0.5; 35310447Snilay@cs.wisc.edu } 35410447Snilay@cs.wisc.edu 35510447Snilay@cs.wisc.edu return out; 35610447Snilay@cs.wisc.edu } 35710447Snilay@cs.wisc.edu 35810447Snilay@cs.wisc.edu} // namespace DSENT 35910447Snilay@cs.wisc.edu 360