Exemplo n.º 1
0
    def set_device_temperature(self, T):
        """Change the temperature of the device. VTO, KP and PHI get updated.
		"""
        self.TEMP = T
        self.VTO = self.VTO - self.TCV * (T - self.TNOM)
        self.KP = self.KP * (T / self.TNOM)**self.BEX
        self.PHI = self.PHI * T/self.TNOM + 3*constants.Vth(self.TNOM)*math.log(T/self.TNOM) \
            - constants.si.Eg(self.TNOM)*T/self.TNOM + constants.si.Eg(T)
Exemplo n.º 2
0
 def __init__(self,
              name,
              IS=None,
              N=None,
              ISR=None,
              NR=None,
              RS=None,
              CJ0=None,
              M=None,
              VJ=None,
              FC=None,
              CP=None,
              TT=None,
              BV=None,
              IBV=None,
              KF=None,
              AF=None,
              FFE=None,
              TEMP=None,
              XTI=None,
              EG=None,
              TBV=None,
              TRS=None,
              TTT1=None,
              TTT2=None,
              TM1=None,
              TM2=None):
     self.name = name
     self.IS = float(IS) if IS is not None else IS_DEFAULT
     self.N = float(N) if N is not None else N_DEFAULT
     self.ISR = float(ISR) if ISR is not None else ISR_DEFAULT
     self.NR = float(NR) if NR is not None else NR_DEFAULT
     self.RS = float(RS) if RS is not None else RS_DEFAULT
     self.CJ0 = float(CJ0) if CJ0 is not None else CJ0_DEFAULT
     self.M = float(M) if M is not None else M_DEFAULT
     self.VJ = float(VJ) if VJ is not None else VJ_DEFAULT
     self.FC = float(FC) if FC is not None else FC_DEFAULT
     self.CP = float(CP) if CP is not None else CP_DEFAULT
     self.TT = float(TT) if TT is not None else TT_DEFAULT
     self.BV = float(BV) if BV is not None else BV_DEFAULT
     self.IBV = float(IBV) if IBV is not None else IBV_DEFAULT
     self.KF = float(KF) if KF is not None else KF_DEFAULT
     self.AF = float(AF) if AF is not None else AF_DEFAULT
     self.FFE = float(FFE) if FFE is not None else FFE_DEFAULT
     self.TEMP = utilities.Celsius2Kelvin(
         float(TEMP)) if TEMP is not None else TEMP_DEFAULT
     self.XTI = float(XTI) if XTI is not None else XTI_DEFAULT
     self.EG = float(EG) if EG is not None else EG_DEFAULT
     self.TBV = float(TBV) if TBV is not None else TBV_DEFAULT
     self.TRS = float(TRS) if TRS is not None else TRS_DEFAULT
     self.TTT1 = float(TTT1) if TTT1 is not None else TTT1_DEFAULT
     self.TTT2 = float(TTT2) if TTT2 is not None else TTT2_DEFAULT
     self.TM1 = float(TM1) if TM1 is not None else TM1_DEFAULT
     self.TM2 = float(TM2) if TM2 is not None else TM2_DEFAULT
     self.T = T_DEFAULT
     self.last_vd = None
     self.VT = constants.Vth(self.T)
Exemplo n.º 3
0
Arquivo: ekv.py Projeto: vovkd/ahkab
    def setup_scaling(self, nq, device):
        """Calculates and stores in self.scaling the following factors:
		  Ut, the thermal voltage,
		  Is, the specific current,
		  Gs, the specific transconductance,
		  Qs, the specific charge.
		"""
        self.scaling.Ut = constants.Vth()
        self.scaling.Is = 2 * nq * self.scaling.Ut**2 * self.KP * device.W / device.L
        self.scaling.Gs = 2 * nq * self.scaling.Ut * self.KP * device.W / device.L
        self.scaling.Qs = 2 * nq * self.scaling.Ut * self.COX
        return
Exemplo n.º 4
0
def get_td(dx, locked_nodes, n=-1):
    """Calculates the damping coefficient for the Newthon method.

    The damping coefficient is choosen as the lowest between:
    - the damping required for the first NR iterations
    - the biggest factor that keeps the change in voltage above the locked nodes
      less than the max variation allowed (nl_voltages_lock_factor*Vth)

    Requires:
    dx - the undamped increment
    locked_nodes - a vector of tuples of nodes that are a port of a NL component
    n - the newthon iteration counter
    k - the maximum number of Vth allowed on a NL component

    Note:
    If n is set to -1 (or any negative value), td is independent from the iteration number.

    Returns: a float, the damping coefficient (td)
    """

    if not options.nr_damp_first_iters or n < 0:
        td = 1
    else:
        if n < 10:
            td = 1e-2
        elif n < 20:
            td = 0.1
        else:
            td = 1
    td_new = 1
    if options.nl_voltages_lock:
        for (n1, n2) in locked_nodes:
            if n1 != 0:
                if n2 != 0:
                    if abs(
                            dx[n1 - 1, 0] - dx[n2 - 1, 0]
                    ) > options.nl_voltages_lock_factor * constants.Vth():
                        td_new = (options.nl_voltages_lock_factor *
                                  constants.Vth()) / abs(dx[n1 - 1, 0] -
                                                         dx[n2 - 1, 0])
                else:
                    if abs(
                            dx[n1 - 1, 0]
                    ) > options.nl_voltages_lock_factor * constants.Vth():
                        td_new = (options.nl_voltages_lock_factor *
                                  constants.Vth()) / abs(dx[n1 - 1, 0])
            else:
                if abs(dx[n2 - 1, 0]
                       ) > options.nl_voltages_lock_factor * constants.Vth():
                    td_new = (options.nl_voltages_lock_factor *
                              constants.Vth()) / abs(dx[n2 - 1, 0])
            if td_new < td:
                td = td_new
    return td
Exemplo n.º 5
0
    def update_status_dictionary(self, ports_v):
        if self.opdict is None:
            self.opdict = {}
        if not (self.opdict['state'] == ports_v[0] and self.opdict.has_key('gmd')) or \
            not (self.opdict['state'] == ports_v[0] and self.opdict.has_key('gmg')) or \
            not (self.opdict['state'] == ports_v[0] and self.opdict.has_key('gms')) or \
                not (self.opdict['state'] == ports_v[0] and self.opdict.has_key('Ids')):

            self.opdict['state'] == ports_v[0]
            self.opdict['gmd'] = self.g(0, ports_v[0], 0)
            self.opdict['gmg'] = self.g(0, ports_v[0], 1)
            self.opdict['gms'] = self.g(0, ports_v[0], 2)
            self.opdict['Ids'] = self.i(0, ports_v[0])

        gmd = self.opdict['gmd']
        gmg = self.opdict['gmg']
        gms = self.opdict['gms']
        ids = self.opdict['Ids']

        if ids == 0:
            TEF = float('nan')
        else:
            TEF = abs(gms * constants.Vth() / ids)
        self.opdict['TEF'] = TEF
Exemplo n.º 6
0
    def __init__(self, name=None, TYPE='n', TNOM=None, COX=None, \
    GAMMA=None, NSUB=None, PHI=None, VTO=None, KP=None, \
    LAMBDA=None, AKP=None, AVT=None,\
    TOX=None, VFB=None, U0=None, TCV=None, BEX=None):

        self.scaling = scaling_holder()

        self.name = "model_mosq0" if name is None else name
        Vth = constants.Vth()
        self.TNOM = float(TNOM) if TNOM is not None else constants.Tref
        #print "TYPE IS:" + TYPE
        self.NPMOS = 1 if TYPE == 'n' else -1

        # optional parameters (no defaults)
        self.TOX = float(TOX) if TOX is not None else None
        self.NSUB = float(NSUB) if NSUB is not None else None
        self.VFB = self.NPMOS * float(VFB) if VFB is not None else None
        self.U0 = float(U0) if U0 is not None else None

        # crucial parameters
        if COX is not None:
            self.COX = float(COX)
        elif TOX is not None:
            self.COX = constants.si.eox / TOX
        else:
            self.COX = COX_DEFAULT

        if GAMMA is not None:
            self.GAMMA = float(GAMMA)
        elif NSUB is not None:
            self.GAMMA = math.sqrt(2 * constants.e * constants.si.esi * NSUB *
                                   10**6 / self.COX)
        else:
            self.GAMMA = GAMMA_DEFAULT
        if PHI is not None:
            self.PHI = float(PHI)
        elif NSUB is not None:
            self.PHI = 2 * constants.Vth(self.TNOM) * math.log(
                NSUB * 10**6 / constants.si.ni(self.TNOM))
        else:
            self.PHI = PHI_DEFAULT
        if VTO is not None:
            self.VTO = self.NPMOS * float(VTO)
            if self.VTO < 0:
                print "(W): model %s has internal negative VTO (%f V)." % (
                    self.name, self.VTO)
        elif VFB is not None:
            self.VTO = VFB + PHI + GAMMA * PHI  #inv here??
        else:
            self.VTO = self.NPMOS * VTO_DEFAULT

        if KP is not None:
            self.KP = float(KP)
        elif U0 is not None:
            self.KP = (U0 * 10**-4) * self.COX
        else:
            self.KP = KP_DEFAULT

        self.LAMBDA = LAMBDA if LAMBDA is not None else LAMBDA_DEFAULT
        # Intrinsic model temperature parameters
        self.TCV = self.NPMOS * float(
            TCV) if TCV is not None else self.NPMOS * TCV_DEFAULT
        self.BEX = float(BEX) if BEX is not None else BEX_DEFAULT

        # Monte carlo
        self.AVT = AVT if AVT is not None else AVT_DEFAULT
        self.AKP = AKP if AKP is not None else AKP_DEFAULT

        self.set_device_temperature(constants.T)

        sc, sc_reason = self._self_check()
        if not sc:
            raise Exception, sc_reason + " out of range"
Exemplo n.º 7
0
 def get_ip_abs_err(self, device):
     """Absolute error to be enforced in the calculation of the normalized currents.
     """
     return options.iea / (2.0 * constants.Vth(self.TEMP)**2.0 * self.KP *
                           device.M * device.W / device.L)
Exemplo n.º 8
0
    def __init__(self,
                 name=None,
                 TYPE='n',
                 TNOM=None,
                 COX=None,
                 GAMMA=None,
                 NSUB=None,
                 PHI=None,
                 VTO=None,
                 KP=None,
                 XJ=None,
                 LAMBDA=None,
                 TOX=None,
                 VFB=None,
                 U0=None,
                 TCV=None,
                 BEX=None):

        self.scaling = scaling_holder()

        self.name = "model_ekv0" if name is None else name
        self.TNOM = float(TNOM) if TNOM is not None else constants.Tref
        self.NPMOS = 1 if TYPE == 'n' else -1

        # optional parameters (no defaults)
        self.TOX = float(TOX) if TOX is not None else None
        self.NSUB = float(NSUB) if NSUB is not None else None
        self.VFB = self.NPMOS * float(VFB) if VFB is not None else None
        self.U0 = float(U0) if U0 is not None else None

        # crucial parameters
        if COX is not None:
            self.COX = float(COX)
        elif TOX is not None:
            self.COX = constants.si.eox / TOX
        else:
            self.COX = COX_DEFAULT

        if GAMMA is not None:
            self.GAMMA = float(GAMMA)
        elif NSUB is not None:
            self.GAMMA = math.sqrt(2.0 * constants.e * constants.si.esi *
                                   NSUB * 10**6 / self.COX)
        else:
            self.GAMMA = GAMMA_DEFAULT
        if PHI is not None:
            self.PHI = float(PHI)
        elif NSUB is not None:
            self.PHI = 2. * constants.Vth(self.TNOM) * math.log(
                NSUB * 10.0**6.0 / constants.si.ni(self.TNOM))
        else:
            self.PHI = PHI_DEFAULT
        if VTO is not None:
            self.VTO = self.NPMOS * float(VTO)
            if self.VTO < 0:
                print "(W): model %s has internal negative VTO (%f V)." % (
                    self.name, self.VTO)
        elif VFB is not None:
            self.VTO = VFB + PHI + GAMMA * PHI  # inv here??
        else:
            self.VTO = self.NPMOS * VTO_DEFAULT

        if KP is not None:
            self.KP = float(KP)
        elif U0 is not None:
            self.KP = (U0 * 10.0**-4) * self.COX
        else:
            self.KP = KP_DEFAULT

        self.LAMBDA = LAMBDA if LAMBDA is not None else LAMBDA_DEFAULT
        self.XJ = XJ if XJ is not None else XJ_DEFAULT
        self.UCRIT = UCRIT_DEFAULT
        # Intrinsic model temperature parameters
        self.TCV = self.NPMOS * \
            float(TCV) if TCV is not None else self.NPMOS * TCV_DEFAULT
        self.BEX = float(BEX) if BEX is not None else BEX_DEFAULT

        self.set_device_temperature(constants.T)

        # Setup switches
        self.SATLIM = math.exp(4.0)
        self.WMSI_factor = 10
        self.NR_damp_factor = options.nl_voltages_lock_factor

        sc, sc_reason = self._self_check()
        if not sc:
            raise Exception, sc_reason + " out of range"
Exemplo n.º 9
0
            WMSI = 0
        else:
            WMSI = 1
        opdict.update({'WMSI': WMSI})

        if debug:
            print "current:", Ids

        return Ids, qf, qr

    def get_leq_virp(self, device, (vd, vg, vs), Vp, Leff, ifn):
        # if ifn > 0 and Vp - constants.Vth()*vd > 0:
        assert vd >= vs
        Vc = self.UCRIT * device.N * Leff
        Vdss  = Vc * \
            (math.sqrt(.25 + constants.Vth() / Vc * math.sqrt(ifn)) - .5)
        # eq. 46
        # Drain-to-source saturation voltage for reverse normalized current,
        # eq. 47
        Vdssp = Vc * (math.sqrt(.25 + constants.Vth() / Vc * (math.sqrt(ifn) - .75 * math.log(ifn))) - .5) + \
            constants.Vth() * (math.log(.5 * Vc / constants.Vth()) - .6)

        # channel length modulation
        vser_1 = math.sqrt(ifn) - Vdss / constants.Vth()
        # if vser_1 < 0:
        #   vser_1 = 0
        Vds = (vd - vs) * .5 * constants.Vth()
        delta_v = 4.0 * constants.Vth() * math.sqrt(
            self.LAMBDA * vser_1 + 1.0 / 64)  # eq. 48
        Vip = math.sqrt(Vdss**2 + delta_v**2) - math.sqrt(
            (Vds - Vdss)**2 + delta_v**2)  # eq 50