Beispiel #1
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables, given temp in deg. C
     """
     # Remove tape if present
     ad.delete_tape(self)
     # First calculate variables from base class
     IMOS.set_temp_vars(self, temp)
     # Absolute temperature
     Tabs = temp + const.T0
     # Temperature-adjusted egap
     egap_t = self.eg0 - .000702 * (Tabs**2) / (Tabs + 1108.)
     # Thermal voltage
     Vt = const.k * Tabs / const.q
     # Adjust junction temperatures
     if self.ad:
         self.dj.set_temp_vars(Tabs, self.__Tnabs, Vt, 
                               self.__egapn, egap_t)
     if self.pd:
         self.djsw.set_temp_vars(Tabs, self.__Tnabs, Vt, 
                                 self.__egapn, egap_t)
     if self.asrc:
         self.sj.set_temp_vars(Tabs, self.__Tnabs, Vt, 
                               self.__egapn, egap_t)
     if self.ps:
         self.sjsw.set_temp_vars(Tabs, self.__Tnabs, Vt, 
                                 self.__egapn, egap_t)
Beispiel #2
0
    def set_temp_vars(self, temp):
        """
        Calculate temperature-dependent variables, given temp in deg. C
        """
        ad.delete_tape(self)
        # Absolute temperature (note self.temp is in deg. C)
        self.Tabs = const.T0 + temp
        # Thermal voltage
        self.vt = const.k * self.Tabs / const.q
        # Temperature-adjusted egap
        self.egap_t = self.eg0 - .000702 * (self.Tabs**2) / (self.Tabs + 1108.)
        # Everything else is handled by junctions
        self.diogs.set_temp_vars(self.Tabs, self.Tnomabs, self.vt, self.egapn,
                                 self.egap_t)
        self.diogd.set_temp_vars(self.Tabs, self.Tnomabs, self.vt, self.egapn,
                                 self.egap_t)

        delta_T = temp - self.tnom
        self._k6 = self.nr * self.vt
        self._Vt0 = self.vt0 * (1. + (delta_T * self.avt0) +
                                (delta_T**2 * self.bvt0))
        if (self.tbet):
            self._Beta = self.beta * pow(1.01, (delta_T * self.tbet))
        else:
            self._Beta = self.beta

        if self.tme * self.tm != 0.:
            self._idsFac = pow((1. + delta_T * self.tm), self.tme)
        else:
            self._idsFac = 1.
Beispiel #3
0
    def set_temp_vars(self, temp):
        """
        Calculate temperature-dependent variables, given temp in deg. C
        """
        # Delete AD tape (if any)
        ad.delete_tape(self)
        # Absolute temperature (note self.temp is in deg. C)
        T = const.T0 + temp
        # Thermal voltage
        self._Vt = const.k * T / const.q
        # threshold voltage
        vt0T = self._vt0 - self._tcv * (T - self._Tn)
        self._vt0a = vt0T + self.avto / self._sga
        kpT = self.kp * pow(T / self._Tn, self.bex)
        self.kpa = kpT * (1 + self.akp / self._sga)
        # Clip to zero if negative
        self.kpa = ad.condassign(self.kpa, self.kpa, 0.0)
        self._t_ucrit = self.ucrit * pow(T / self._Tn, self.ucex)
        # Energy gap
        egT = 1.16 - 0.000702 * T * T / (T + 1108.0)
        self.phiT = (
            self.phi * T / self.Tref - 3.0 * self._Vt * np.log(T / self.Tref) - self.egTref * T / self.Tref + egT
        )
        self._t_ibb = self.ibb * (1.0 + self.ibbt * (T - self.Tref))

        self._vc = self._t_ucrit * self._leff * self.ns
        self._qb0 = self._gammaa * np.sqrt(self.phiT)
        # Noise variables
        self._kSt = 4.0 * const.k * T
Beispiel #4
0
    def set_temp_vars(self, temp):
        """
        Calculate temperature-dependent variables, given temp in deg. C
        """
        # Delete AD tape (if any)
        ad.delete_tape(self)
        # Absolute temperature (note self.temp is in deg. C)
        T = const.T0 + temp
        # Thermal voltage
        self._Vt = const.k * T / const.q
        # threshold voltage
        vt0T = self._vt0 - self._tcv * (T - self._Tn)
        self._vt0a = vt0T + self.avto / self._sga
        kpT = self.kp * pow(T / self._Tn, self.bex)
        self.kpa = kpT * (1 + self.akp / self._sga)
        # Clip to zero if negative
        self.kpa = ad.condassign(self.kpa, self.kpa, 0.)
        self._t_ucrit = self.ucrit * pow(T / self._Tn, self.ucex)
        # Energy gap
        egT = 1.16 - 0.000702 * T * T / (T + 1108.)
        self.phiT = self.phi * T / self.Tref \
            - 3. * self._Vt * np.log(T / self.Tref) \
            - self.egTref * T / self.Tref + egT
        self._t_ibb = self.ibb * (1. + self.ibbt * (T - self.Tref))

        self._vc = self._t_ucrit * self._leff * self.ns
        self._qb0 = self._gammaa * np.sqrt(self.phiT)
        # Noise variables
        self._kSt = 4. * const.k * T
Beispiel #5
0
    def process_params(self, thermal=False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        ad.delete_tape(self)
        if self.type == 'n':
            self._tf = 1.
        elif self.type == 'p':
            self._tf = -1.
        else:
            raise cir.CircuitError(
                '{0}: unrecognized type: {1}. Valid types are "n" or "p"'.
                format(self.instanceName, self.type))

        # Make sure vth is positive for calculations
        self._vth = abs(self.vth)
        self._tcv = np.abs(self.tcv)

        # Nominal abs temperature
        self._Tn = const.T0 + self.tnom
        # Nominal Thermal voltage
        self._Vtn = const.k * self._Tn / const.q
        self._mu = self.isq * 2. / (self.n * self.cox * self._Vtn**2)
        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #6
0
    def set_temp_vars(self, temp):
        """
        Calculate temperature-dependent variables, given temp in deg. C
        """
        ad.delete_tape(self)
        # Absolute temperature (note self.temp is in deg. C)
        absTemp = const.T0 + temp
        # Thermal voltage
        self._Vt = const.k * absTemp / const.q
        # -------------------------------------------------------

        self._ToTnm1 = absTemp / self._Tn - 1.

        self.vsattemp = self.vsat - self.at * self._ToTnm1
        self.rds0 = (self.rdsw + self.prt * self._ToTnm1) \
            / pow(self.weff * 1e6, self.wr)

        self.V0 = self.vbi - self.phi

        #Mobility calculation
        self._ua = self.ua + self.ua1 * self._ToTnm1
        self._ub = self.ub + self.ub1 * self._ToTnm1
        self._uc = self.uc + self.uc1 * self._ToTnm1

        self.u0temp = self._u0 * pow(absTemp / self._Tn, self.ute) 
Beispiel #7
0
    def process_params(self, thermal = False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        ad.delete_tape(self)
        if self.type == 'n':
            self._tf = 1.
        elif self.type == 'p':
            self._tf = -1.
        else:
            raise cir.CircuitError(
                '{0}: unrecognized type: {1}. Valid types are "n" or "p"'.format(self.nodeName, self.type))

        # Make sure vth is positive for calculations
        self._vth = abs(self.vth)
        self._tcv = np.abs(self.tcv)

        # Nominal abs temperature
        self._Tn = const.T0 + self.tnom
        # Nominal Thermal voltage
        self._Vtn = const.k * self._Tn / const.q
        self._mu = self.isq * 2. / (self.n * self.cox * self._Vtn**2)
        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #8
0
    def set_temp_vars(self, temp):
        """
        Calculate temperature-dependent variables, given temp in deg. C
        """
        ad.delete_tape(self)
        # Absolute temperature (note self.temp is in deg. C)
        self.Tabs = const.T0 + temp
        # Thermal voltage
        self.vt = const.k * self.Tabs / const.q
        # Temperature-adjusted egap
        self.egap_t = self.eg0 - 0.000702 * (self.Tabs ** 2) / (self.Tabs + 1108.0)
        # Everything else is handled by junctions
        self.diogs.set_temp_vars(self.Tabs, self.Tnomabs, self.vt, self.egapn, self.egap_t)
        self.diogd.set_temp_vars(self.Tabs, self.Tnomabs, self.vt, self.egapn, self.egap_t)

        delta_T = temp - self.tnom
        self._k6 = self.nr * self.vt
        self._Vt0 = self.vt0 * (1.0 + (delta_T * self.avt0) + (delta_T ** 2 * self.bvt0))
        if self.tbet:
            self._Beta = self.beta * pow(1.01, (delta_T * self.tbet))
        else:
            self._Beta = self.beta

        if self.tme and self.tm:
            self._idsFac = pow((1.0 + delta_T * self.tm), self.tme)
        else:
            self._idsFac = 1.0
Beispiel #9
0
    def set_temp_vars(self, temp):
        """
        Calculate temperature-dependent variables, given temp in deg. C
        """
        ad.delete_tape(self)
        # Absolute temperature (note self.temp is in deg. C)
        absTemp = const.T0 + temp
        # Thermal voltage
        self._Vt = const.k * absTemp / const.q
        # -------------------------------------------------------

        self._ToTnm1 = absTemp / self._Tn - 1.

        self.vsattemp = self.vsat - self.at * self._ToTnm1
        self.rds0 = (self.rdsw + self.prt * self._ToTnm1) \
            / pow(self.weff * 1e6, self.wr)

        self.V0 = self.vbi - self.phi

        #Mobility calculation
        self._ua = self.ua + self.ua1 * self._ToTnm1
        self._ub = self.ub + self.ub1 * self._ToTnm1
        self._uc = self.uc + self.uc1 * self._ToTnm1

        self.u0temp = self._u0 * pow(absTemp / self._Tn, self.ute) 
Beispiel #10
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables, given temp in deg. C
     """
     # Remove tape if present
     ad.delete_tape(self)
     # First calculate variables from base class
     IMOS.set_temp_vars(self, temp)
     # Absolute temperature
     Tabs = temp + const.T0
     # Temperature-adjusted egap
     egap_t = self.eg0 - .000702 * (Tabs**2) / (Tabs + 1108.)
     # Thermal voltage
     Vt = const.k * Tabs / const.q
     # Adjust junction temperatures
     if self.ad != 0.:
         self.dj.set_temp_vars(Tabs, self.__Tnabs, Vt, self.__egapn,
                               egap_t)
     if self.pd != 0.:
         self.djsw.set_temp_vars(Tabs, self.__Tnabs, Vt, self.__egapn,
                                 egap_t)
     if self.asrc != 0.:
         self.sj.set_temp_vars(Tabs, self.__Tnabs, Vt, self.__egapn,
                               egap_t)
     if self.ps != 0.:
         self.sjsw.set_temp_vars(Tabs, self.__Tnabs, Vt, self.__egapn,
                                 egap_t)
Beispiel #11
0
    def set_temp_vars(self, temp):
        """
        Calculate temperature-dependent variables, given temp in deg. C
        """
        ad.delete_tape(self)

        # Absolute temperature (note self.temp is in deg. C)
        T = const.T0 + temp
        # Thermal voltage
        self.Vt = const.k * T / const.q
Beispiel #12
0
    def set_temp_vars(self, temp):
        """
        Calculate temperature-dependent variables, given temp in deg. C
        """
        ad.delete_tape(self)

        # Absolute temperature (note self.temp is in deg. C)
        T = const.T0 + temp
        # Thermal voltage
        self.Vt = const.k * T / const.q
Beispiel #13
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables, given temp in deg. C
     """
     # Remove tape if present
     ad.delete_tape(self)
     # First calculate variables from base class
     IBJT.set_temp_vars(self, temp)
     # Adjust collector-bulk junction temperature
     self.cbjtn.set_temp_vars(self.Tabs, self.Tnomabs, self.vt,
                              self.egapn, self.egap_t)
Beispiel #14
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables, given temp in deg. C
     """
     # Remove tape if present
     ad.delete_tape(self)
     # First calculate variables from base class
     IBJT.set_temp_vars(self, temp)
     # Adjust collector-bulk junction temperature
     self.cbjtn.set_temp_vars(self.Tabs, self.Tnomabs, self.vt, 
                              self.egapn, self.egap_t)
Beispiel #15
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables for temp given in C
     """
     # Delete AD tape (if any)
     ad.delete_tape(self)
     # Absolute temperature (note temp is in deg. C)
     # T = const.T0 + temp
     deltaT = temp - self.tnom
     self.g /= (1. + (self.tc1 + self.tc2 * deltaT) * deltaT)
     self._St =  4. * const.k * (temp + const.T0) * self.g
     # Set this here to keep VCCS in sync with temperature 
     self.linearVCCS = [((0, 1), (0, 1), self.g)]
Beispiel #16
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables for temp given in C
     """
     # Delete AD tape (if any)
     ad.delete_tape(self)
     # Absolute temperature (note temp is in deg. C)
     # T = const.T0 + temp
     deltaT = temp - self.tnom
     self.g /= (1. + (self.tc1 + self.tc2 * deltaT) * deltaT)
     self._St = 4. * const.k * (temp + const.T0) * self.g
     # Set this here to keep VCCS in sync with temperature
     self.linearVCCS = [((0, 1), (0, 1), self.g)]
Beispiel #17
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables for temp given in C
     """
     # Make sure tape is re-generated
     ad.delete_tape(self)
     # Absolute temperature
     Tabs = temp + const.T0
     # Thermal voltage
     self.vt = const.k * Tabs / const.q
     # Temperature-adjusted egap
     egap_t = self.eg0 - .000702 * (Tabs**2) / (Tabs + 1108.)
     self._Sthermal = 4. * const.k * Tabs * self.rs
     # Everything else is handled by the PN junction
     self.jtn.set_temp_vars(Tabs, self.Tnomabs, self.vt, self.egapn, egap_t)
Beispiel #18
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables for temp given in C
     """
     # Make sure tape is re-generated
     ad.delete_tape(self)
     # Absolute temperature
     Tabs = temp + const.T0
     # Thermal voltage
     self.vt = const.k * Tabs / const.q
     # Temperature-adjusted egap
     egap_t = self.eg0 - .000702 * (Tabs**2) / (Tabs + 1108.)
     self._Sthermal = 4. * const.k * Tabs * self.rs
     # Everything else is handled by the PN junction
     self.jtn.set_temp_vars(Tabs, self.Tnomabs, self.vt, self.egapn, egap_t)
Beispiel #19
0
    def process_params(self, thermal=False):
        # Make sure tape is re-generated
        ad.delete_tape(self)
        # Remove internal terminals
        self.clean_internal_terms()

        # Set flag to add thermal ports if needed
        self.__addThermalPorts = True

        # Define topology first
        # Needs at least one internal terminal:
        tx = self.add_internal_term('x', 's.v.')
        tref = self.add_reference_term()
        self.linearVCCS = [((0, 1), (tx, tref), glVar.gyr)]
        # Nonlinear device attributes
        self.csOutPorts = [(0, 1), (tref, tx)]
        self.noisePorts = [(0, 1)]
        self.controlPorts = [(tx, tref)]

        if self.rs != 0.:
            # Needs one more terminal
            t2 = self.add_internal_term('t2', 'V')
            g = self.area / self.rs
            self.linearVCCS = [((t2, 1), (tx, tref), glVar.gyr),
                               ((0, t2), (0, t2), g)]
            # Nonlinear device outputs change
            self.csOutPorts = [(t2, 1), (tref, tx)]
            self.noisePorts = [(t2, 1), (0, t2)]

        # Nonlinear device attributes (defined in process_params())
        self.qsOutPorts = []
        self._qd = False
        if self.tt + self.cj0 != 0.:
            # Add charge source (otherwise the charge calculation is ignored)
            self.qsOutPorts.append(self.csOutPorts[0])
            self._qd = True

        # Absolute nominal temperature
        self.Tnomabs = self.tnom + const.T0
        self.egapn = self.eg0 - .000702 * (self.Tnomabs**2) \
            / (self.Tnomabs + 1108.)

        # Calculate variables in junction
        self.jtn.process_params(self.isat, self.n, self.fc, self.cj0, self.vj,
                                self.m, self.xti, self.eg0, self.Tnomabs)
        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #20
0
    def process_params(self, thermal = False):
        # Make sure tape is re-generated
        ad.delete_tape(self)
        # Remove internal terminals
        self.clean_internal_terms()

        # Set flag to add thermal ports if needed
        self.__addThermalPorts = True

        # Define topology first
        # Needs at least one internal terminal: 
        tx = self.add_internal_term('x', 's.v.')
        tref = self.add_reference_term() 
        self.linearVCCS = [((0, 1), (tx, tref), glVar.gyr)]
        # Nonlinear device attributes
        self.csOutPorts = [(0, 1), (tref, tx)]
        self.noisePorts = [(0, 1)]
        self.controlPorts = [(tx, tref)]

        if self.rs != 0.:
            # Needs one more terminal
            t2 = self.add_internal_term('t2', 'V')
            g = self.area / self.rs
            self.linearVCCS = [((t2, 1), (tx, tref), glVar.gyr),
                               ((0, t2), (0, t2), g)]
            # Nonlinear device outputs change
            self.csOutPorts = [(t2, 1), (tref, tx)]
            self.noisePorts = [(t2, 1), (0, t2)]

        # Nonlinear device attributes (defined in process_params())
        self.qsOutPorts = [ ]
        self._qd = False
        if self.tt + self.cj0 != 0.:
            # Add charge source (otherwise the charge calculation is ignored)
            self.qsOutPorts.append(self.csOutPorts[0])
            self._qd = True

        # Absolute nominal temperature
        self.Tnomabs = self.tnom + const.T0
        self.egapn = self.eg0 - .000702 * (self.Tnomabs**2) \
            / (self.Tnomabs + 1108.)

        # Calculate variables in junction
        self.jtn.process_params(self.isat, self.n, self.fc, self.cj0, self.vj, 
                                self.m, self.xti, self.eg0, self.Tnomabs)
        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #21
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables, given temp in deg. C
     """
     ad.delete_tape(self)
     # Absolute temperature (note self.temp is in deg. C)
     T = const.T0 + temp
     # Thermal voltage
     self._Vt = const.k * T / const.q
     # threshold voltage
     self._vthT = self._vth - self._tcv * (T - self._Tn)
     # Mobility
     muT = self._mu * (T / self._Tn)**self.bex
     # IS (specific current)
     s = self.w / self.l
     self._IS = .5 * s * self.n * muT * self.cox * self._Vt**2
Beispiel #22
0
 def set_temp_vars(self, temp):
     """
     Calculate temperature-dependent variables, given temp in deg. C
     """
     ad.delete_tape(self)
     # Absolute temperature (note self.temp is in deg. C)
     T = const.T0 + temp
     # Thermal voltage
     self._Vt = const.k * T / const.q
     # threshold voltage
     self._vthT = self._vth - self._tcv * (T - self._Tn)
     # Mobility
     muT = self._mu * (T / self._Tn)**self.bex
     # IS (specific current)
     s = self.w / self.l
     self._IS = .5 * s * self.n * muT * self.cox * self._Vt**2
Beispiel #23
0
    def process_params(self, thermal = False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        
        # Make sure tape is re-generated
        ad.delete_tape(self)
        # Remove internal terminals
        self.clean_internal_terms()
        # Set flag to add thermal ports if needed
        self.__addThermalPorts = True

        # Define topology first
        if self.rs:
            # Need 1 internal terminal
            t2 = self.add_internal_term('t2', 'V')
            g = self.area / self.rs
            self.linearVCCS = [((0, t2), (0, t2), g)]
            # Nonlinear device attributes
            self.csOutPorts = [(t2, 1)]
            self.noisePorts = [(t2, 1), (0, t2)]
            self.controlPorts = [(t2, 1)]
        else:
            # Nonlinear device attributes
            self.csOutPorts = [(0, 1)]
            self.noisePorts = [(0, 1)]
            self.controlPorts = [(0, 1)]

        self.qsOutPorts = [ ]
        self._qd = False
        if self.tt or self.cj0:
            # Add charge source (otherwise the charge calculation is ignored)
            self.qsOutPorts = self.csOutPorts
            self._qd = True

        # Absolute nominal temperature
        self.Tnomabs = self.tnom + const.T0
        self.egapn = self.eg0 - .000702 * (self.Tnomabs**2) \
            / (self.Tnomabs + 1108.)

        # Calculate variables in junction
        self.jtn.process_params(self.isat, self.n, self.fc, self.cj0, self.vj, 
                                self.m, self.xti, self.eg0, self.Tnomabs)
        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #24
0
    def process_params(self, thermal=False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.

        # Make sure tape is re-generated
        ad.delete_tape(self)
        # Remove internal terminals
        self.clean_internal_terms()
        # Set flag to add thermal ports if needed
        self.__addThermalPorts = True

        # Define topology first
        if self.rs != 0.:
            # Need 1 internal terminal
            t2 = self.add_internal_term('t2', 'V')
            g = self.area / self.rs
            self.linearVCCS = [((0, t2), (0, t2), g)]
            # Nonlinear device attributes
            self.csOutPorts = [(t2, 1)]
            self.noisePorts = [(t2, 1), (0, t2)]
            self.controlPorts = [(t2, 1)]
        else:
            # Nonlinear device attributes
            self.csOutPorts = [(0, 1)]
            self.noisePorts = [(0, 1)]
            self.controlPorts = [(0, 1)]

        self.qsOutPorts = []
        self._qd = False
        if self.tt + self.cj0 != 0.:
            # Add charge source (otherwise the charge calculation is ignored)
            self.qsOutPorts = self.csOutPorts
            self._qd = True

        # Absolute nominal temperature
        self.Tnomabs = self.tnom + const.T0
        self.egapn = self.eg0 - .000702 * (self.Tnomabs**2) \
            / (self.Tnomabs + 1108.)

        # Calculate variables in junction
        self.jtn.process_params(self.isat, self.n, self.fc, self.cj0, self.vj,
                                self.m, self.xti, self.eg0, self.Tnomabs)
        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #25
0
    def process_params(self, thermal = False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        ad.delete_tape(self)

        if self.type == 'n':
            self._tf = 1.
        elif self.type == 'p':
            self._tf = -1.
        else:
            raise cir.CircuitError(
                '{0}: unrecognized type: {1}. Valid types are "n" or "p"'.format(self.instanceName, self.type))

        # Nominal abs temperature
        self._Tn = const.T0 + self.tnom

        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #26
0
    def process_params(self, thermal = False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.

        # Delete AD tape (if any)
        ad.delete_tape(self)
        # Access to global variables is through the glVar 
        if not self.r and not (self.rsh and self.l and self.w):
            raise cir.CircuitError(self.nodeName 
                                   + ': Resistance can not be zero')

        if self.r:
            # if R is given it overrides rsh et ale
            self.g = 1. / self.r
        else:
            self.g = (self.w-self.narrow) / (self.l-self.narrow) / self.rsh

        if not thermal:
            # Adjust according to temperature
            self.set_temp_vars(self.temp)
Beispiel #27
0
    def process_params(self, thermal=False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.

        # Delete AD tape (if any)
        ad.delete_tape(self)
        # Access to global variables is through the glVar
        if not self.r and not (self.rsh and self.l and self.w):
            raise cir.CircuitError(self.instanceName +
                                   ': Resistance can not be zero')

        if self.r != 0.:
            # if R is given it overrides rsh et ale
            self.g = 1. / self.r
        else:
            self.g = (self.w - self.narrow) / (self.l - self.narrow) / self.rsh

        if not thermal:
            # Adjust according to temperature
            self.set_temp_vars(self.temp)
Beispiel #28
0
    def process_params(self, thermal=False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        ad.delete_tape(self)

        if self.type == 'n':
            self._tf = 1.
        elif self.type == 'p':
            self._tf = -1.
        else:
            raise cir.CircuitError(
                '{0}: unrecognized type: {1}. Valid types are "n" or "p"'.
                format(self.instanceName, self.type))

        # Nominal abs temperature
        self._Tn = const.T0 + self.tnom

        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #29
0
    def process_params(self, thermal=False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        ad.delete_tape(self)
        # Time-delayed control port
        self.delayedContPorts = [(1, 2, self.tau), (1, 0, self.tau)]

        # Absolute nominal temperature
        self.Tnomabs = self.tnom + const.T0
        self.egapn = self.eg0 - 0.000702 * (self.Tnomabs ** 2) / (self.Tnomabs + 1108.0)

        # Calculate variables in junctions
        self.diogs.process_params(
            self.isat, self.n, self.fcc, self.cgs0, self.vbi, self.mgs, self.xti, self.eg0, self.Tnomabs
        )
        self.diogd.process_params(
            self.isat, self.n, self.fcc, self.cgd0, self.vbi, self.mgd, self.xti, self.eg0, self.Tnomabs
        )
        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #30
0
    def process_params(self, thermal=False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        ad.delete_tape(self)
        # Time-delayed control port
        self.delayedContPorts = [(1, 2, self.tau), (1, 0, self.tau)]

        # Absolute nominal temperature
        self.Tnomabs = self.tnom + const.T0
        self.egapn = self.eg0 - .000702 * (self.Tnomabs**2) \
            / (self.Tnomabs + 1108.)

        # Calculate variables in junctions
        self.diogs.process_params(self.isat, self.n, self.fcc, self.cgs0,
                                  self.vbi, self.mgs, self.xti, self.eg0,
                                  self.Tnomabs)
        self.diogd.process_params(self.isat, self.n, self.fcc, self.cgd0,
                                  self.vbi, self.mgd, self.xti, self.eg0,
                                  self.Tnomabs)
        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #31
0
    def process_params(self, thermal=False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        # import pdb; pdb.set_trace()

        # Delete AD tape (if any)
        ad.delete_tape(self)
        # Any value other than zero uses the simple function
        if self.ekvint:
            self.interp = f_simple
        else:
            self.interp = f_accurate
        # Set Constants
        self.Tref = 300.15
        self._Tn = self.tnom + const.T0
        vtTref = (const.k * self.Tref) / const.q
        self.egTref = 1.16 - 0.000702 * self.Tref * self.Tref / (self.Tref + 1108.0)
        vtTnom = (const.k * self._Tn) / const.q
        self.egTnom = 1.16 - 0.000702 * self._Tn * self._Tn / (self._Tn + 1108.0)
        niTnom = 1.45e10 * (self._Tn / self.Tref) * np.exp(self.egTref / (2.0 * vtTref) - self.egTnom / (2.0 * vtTnom))
        # For N/P channel
        self._tcv = np.abs(self.tcv)
        if self.type == "n":
            self.eta = 0.5
            self._tf = 1.0
        elif self.type == "p":
            self.eta = 1.0 / 3.0
            self._tf = -1.0
        else:
            raise cir.CircuitError(
                '{0}: unrecognized type: {1}. Valid types are "n" or "p"'.format(self.instanceName, self.type)
            )
        # ---------------------------------------------------------------
        # Calculate any missing parameters from user-defined settings
        # COX
        if (not self.is_set("cox")) and self.tox != None:
            self.cox = const.epOx / self.tox
        # GAMMA
        if (not self.is_set("gamma")) and self.nsub != None:
            self.gamma = np.sqrt(2.0 * const.q * const.epSi * self.nsub * 1.0e6) / self.cox
        # PHI
        if (not self.is_set("phi")) and self.nsub != None:
            self.phi = 2.0 * vtTnom * np.log(self.nsub / niTnom)
        # VT0: if specified, must be with the correct sign, otherwise
        # we have to adjust for P-channel
        if not self.is_set("vt0"):
            if self.vfb != None:
                self.vt0 = self._tf * (self.vfb + self.phi + self.gamma * np.sqrt(self.phi))
            else:
                self.vt0 *= self._tf
        # Make sure vt0 is positive for calculations
        self._vt0 = abs(self.vt0)
        # KP
        if (not self.is_set("kp")) and self.u0 != None:
            self.kp = self.u0 * 1.0e-4 * self.cox  # /*(m^2/cm^2)*/
        # UCRIT
        if (not self.is_set("ucrit")) and (self.vmax != None) and (self.u0 != None):
            self.ucrit = self.vmax / (self.u0 * 1.0e-4)
        # E0: no need for anything since theta != 0 triggers simple
        # mobility model

        # Initialize more variables
        self._weff = self.w + self.dw
        self._leff = self.l + self.dl
        # sqrt gate area
        self._sga = np.sqrt(self.np * self._weff * self.ns * self._leff)
        self._gammaa = self.gamma + self.agamma / self._sga
        # Clip to zero if negative
        if self._gammaa < 0.0:
            self._gammaa = 0.0
        cEps = 0.001936  #  was: 4. * pow(22.e-3, 2)
        cA = 0.028
        xi = cA * (10.0 * self._leff / self.lk - 1.0)
        self._deltavRSCE = 2.0 * self.q0 / (self.cox * pow(1.0 + 0.5 * (xi + np.sqrt(xi * xi + cEps)), 2))

        # constants used in eval_c1qs()
        self._lc = np.sqrt(const.epSi * self.xj / self.cox)
        self._lmin = self.ns * self._leff / 10.0
        self._Cox = self.cox * self.np * self._weff * self.ns * self._leff

        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #32
0
        def process_params(self, thermal = False):
            # Remove tape if present
            ad.delete_tape(self)

            if thermal:
                extraTerms = 2
            else:
                extraTerms = 0

            # First check external connections
            if self.numTerms == 3 + extraTerms:
                self.__addCBjtn = False
            elif self.numTerms == 4 + extraTerms:
                self.__addCBjtn = True
            else:
                raise cir.CircuitError( 
                    '{0}: Wrong number of connections. \
Can only be {1} or {2}, {3} found.'.format(self.nodeName, 
                                           3 + extraTerms,
                                           4 + extraTerms,
                                           self.numTerms))

            # Remove internal terminals
            self.clean_internal_terms()
            # Tell autothermal to re-generate thermal ports
            self.__addThermalPorts = True

            extraVCCS = list()
            if self.re:
                # Add et node and translate port descriptions
                self._et = self.add_internal_term('et', 'V')
                extraVCCS += [((2, self._et), (2, self._et), 
                               self.area / self.re)]
            if self.rc:
                # Add ct node and translate port descriptions
                self._ct = self.add_internal_term('ct', 'V')
                extraVCCS += [((0, self._ct), (0, self._ct), 
                               self.area / self.rc)]

            # Process parameters from intrinsic device: emitter and
            # collector terminals are already substituted.
            IBJT.process_params(self)
            # Calculate variables in junction
            self.cbjtn.process_params(self.iss, self.ns, self.fc, self.cjs, 
                                      self.vjs, self.mjs, self.xti, self.eg, 
                                      self.Tnomabs)
            # Add RE, RC resistors (if any)
            self.linearVCCS += extraVCCS
            if self.__addCBjtn:
                # Add bulk-collector junction
                self.__bccn = len(self.controlPorts)
                self.__bcon = len(self.csOutPorts) 
                self.controlPorts.append((3, self._ct))
                self.csOutPorts.append((3, self._ct))
                if self.cjs:
                    self.qsOutPorts.append((3, self._ct))

                # Initial guess for input ports: 
                try:
                    if len(self.vPortGuess) < len(self.controlPorts):
                        self.vPortGuess = np.concatenate(
                            (self.vPortGuess, [1]), axis=0)
                except AttributeError:
                    # Ignore if vPortGuess not provided
                    pass

            # Adjust temperature
            self.set_temp_vars(self.temp)
Beispiel #33
0
    def process_params(self, thermal = False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        ad.delete_tape(self)
        if self.type == 'n':
            self._tf = 1.
        elif self.type == 'p':
            self._tf = -1.
            # Change parameter default values
            if not self.is_set('u0'):
                self.u0 = 250
        else:
            raise cir.CircuitError(
                '{0}: unrecognized type: {1}. Valid types are "n" or "p"'.format(self.instanceName, self.type))

        # Nominal abs temperature
        self._Tn = const.T0 + self.tnom
        # Nominal Thermal voltage
        self._Vtn = const.k * self._Tn / const.q

        self.factor1 = np.sqrt(const.epSi / const.epOx * self.tox)
        Eg0 = 1.16 - 7.02e-4 * (self._Tn**2) / (self._Tn + 1108.0)
        ni = 1.45e10 * (self._Tn / 300.15) * np.sqrt(self._Tn / 300.15) \
            * np.exp(21.5565981 - Eg0 / (2. * self._Vtn))
        #self.esi = 11.7 * const.epsilon0 (replaced by const.epSi)
        self.ldrn = self.l
        self.wdrn = self.w
        
        t0 = pow(self.ldrn, self.lln)
        t1 = pow(self.wdrn, self.lwn)
        tmp1 = self.ll / t0 + self.lw / t1 + self.lwl / (t0 * t1)
        self.dl = self.lint + tmp1
        #tmp2 = llc / t0 + lwc / t1 + lwlc / (t0 * t1)
        #self.dlc = dlc + tmp2  # ???
        
        t2 = pow(self.ldrn, self.wln)
        t3 = pow(self.wdrn, self.wwn)
        tmp3 = self.wl / t2 + self.ww / t3 + self.wwl / (t2 * t3)
        self.dw = self.wint + tmp3
        #tmp4 = wlc / t2 + wwc / t3 + wwlc / (t2 * t3)
        #self.dwc = dwc + tmp4 # ???
        
        self.leff = self.l - 2.0 * self.dl
        self.weff = self.w - 2.0 * self.dw

        self.AbulkCVfactor = (1. + pow(self.clc/self.leff, self.cle))

        #self.leffCV = l - 2.0 * dlc
        #self.t11 = leffCV * leffCV

        # was epOx = 3.453133e-11
        self.cox = const.epOx / self.tox

        self.phi = 2. * self._Vtn * np.log(self.nch / ni)
        self.sqrtPhi = np.sqrt(self.phi)
        self.phis3 = self.sqrtPhi * self.phi

        self.Xdep0 = np.sqrt(2. * const.epSi / 
                          (const.q * self.nch * 1e6)) * self.sqrtPhi
        self.litl = np.sqrt(3. * self.xj * self.tox)
        self.vbi = self._Vtn * np.log(1.0e20 * self.nch / (ni**2))
        self.cdep0 = np.sqrt(const.q * const.epSi * self.nch * 1e6 
                          / 2. / self.phi)

        if not self.is_set('toxm'):
            self.toxm = self.tox
        if not self.is_set('dsub'):
            self.dsub = self.drout

        self.ldeb = np.sqrt(const.epSi * self._Vtn
                           / (const.q * self.nch * 1e6)) / 3.
        
        #import pdb; pdb.set_trace()
        if (self.k1enable != 0.) and \
                not (self.is_set('k1') or self.is_set('k2')):
            vbx = self.phi - 7.7348e-4  * self.nch * self.xt**2
            # From ngspice
            vbx = -abs(vbx)
            Vbm = -abs(self.vbm)
            gamma1 = 5.753e-12 * np.sqrt(self.nch) / self.cox
            gamma2 = 5.753e-12 * np.sqrt(self.nsub) / self.cox
            T0 = gamma1 - gamma2
            T1 = np.sqrt(self.phi - vbx) - self.sqrtPhi
            T2 = np.sqrt(self.phi * (self.phi - Vbm)) - self.phi
            self._k2 = T0 * T1 / (2. * T2 + Vbm)
            self._k1 = gamma2 - 2. * self._k2 * np.sqrt(self.phi - Vbm)
            # print self._k1, self._k2
        else:
            self._k1 = self.k1
            self._k2 = self.k2
        
        if not self.is_set('vth0'):
            self._vth0 = self.vfb + self.phi + self._k1 * self.sqrtPhi
        else:
            self._vth0 = abs(self.vth0)

        self.k1ox = self._k1 * self.tox / self.toxm
        self.k2ox = self._k2 * self.tox / self.toxm

        t1 = np.sqrt(const.epSi / const.epOx * self.tox * self.Xdep0)
        t0 = ad.safe_exp(-0.5 * self.dsub * self.leff / t1)
        self.theta0vb0 = (t0 + 2.0 * t0**2)
        # From freeda, ngspice:
        self._Tox = 1e8 * self.tox
        
        #Calculation of vbsc(Vbc) and Vbseff
        if self._k2 < 0.:
            self.vbsc = .9 * (self.phi - (.5 * self._k1 / self._k2)**2)
            if self.vbsc > -3.:
                self.vbsc = -3.
            elif self.vbsc < -30.:
                self.vbsc = -30.
        else:
            self.vbsc = -30.

        if self.u0 > 1.:
            self._u0 = self.u0 * 1e-4
        else:
            self._u0 = self.u0 

        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #34
0
    def process_params(self, thermal=False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        # import pdb; pdb.set_trace()

        # Delete AD tape (if any)
        ad.delete_tape(self)
        # Any value other than zero uses the simple function
        if self.ekvint:
            self.interp = f_simple
        else:
            self.interp = f_accurate
        # Set Constants
        self.Tref = 300.15
        self._Tn = self.tnom + const.T0
        vtTref = (const.k * self.Tref) / const.q
        self.egTref = 1.16 - 0.000702 * self.Tref * self.Tref \
            / (self.Tref + 1108.)
        vtTnom = (const.k * self._Tn) / const.q
        self.egTnom = 1.16 - .000702 * self._Tn * self._Tn / (self._Tn + 1108.)
        niTnom = 1.45e10 * (self._Tn / self.Tref) \
            * np.exp(self.egTref / (2. * vtTref) - self.egTnom / (2. * vtTnom))
        # For N/P channel
        self._tcv = np.abs(self.tcv)
        if self.type == 'n':
            self.eta = 0.5
            self._tf = 1.
        elif self.type == 'p':
            self.eta = 1. / 3.
            self._tf = -1.
        else:
            raise cir.CircuitError(
                '{0}: unrecognized type: {1}. Valid types are "n" or "p"'.
                format(self.instanceName, self.type))
        #---------------------------------------------------------------
        # Calculate any missing parameters from user-defined settings
        # COX
        if (not self.is_set('cox')) and self.tox != None:
            self.cox = const.epOx / self.tox
        # GAMMA
        if (not self.is_set('gamma')) and self.nsub != None:
            self.gamma = np.sqrt(
                2. * const.q * const.epSi * self.nsub * 1.e6) / self.cox
        # PHI
        if (not self.is_set('phi')) and self.nsub != None:
            self.phi = 2. * vtTnom * np.log(self.nsub / niTnom)
        # VT0: if specified, must be with the correct sign, otherwise
        # we have to adjust for P-channel
        if (not self.is_set('vt0')):
            if self.vfb != None:
                self.vt0 = self._tf * (self.vfb + self.phi +
                                       self.gamma * np.sqrt(self.phi))
            else:
                self.vt0 *= self._tf
        # Make sure vt0 is positive for calculations
        self._vt0 = abs(self.vt0)
        # KP
        if (not self.is_set('kp')) and self.u0 != None:
            self.kp = self.u0 * 1.e-4 * self.cox  # /*(m^2/cm^2)*/
        # UCRIT
        if (not self.is_set('ucrit')) and (self.vmax != None) and \
                (self.u0 != None):
            self.ucrit = self.vmax / (self.u0 * 1.e-4)
        # E0: no need for anything since theta != 0 triggers simple
        # mobility model

        # Initialize more variables
        self._weff = self.w + self.dw
        self._leff = self.l + self.dl
        # sqrt gate area
        self._sga = np.sqrt(self.np * self._weff * self.ns * self._leff)
        self._gammaa = self.gamma + self.agamma / self._sga
        # Clip to zero if negative
        if self._gammaa < 0.:
            self._gammaa = 0.
        cEps = 0.001936  #  was: 4. * pow(22.e-3, 2)
        cA = 0.028
        xi = cA * (10. * self._leff / self.lk - 1.)
        self._deltavRSCE = 2. * self.q0 / \
            (self.cox * pow(1. + 0.5 * (xi + np.sqrt(xi*xi + cEps)), 2))

        # constants used in eval_c1qs()
        self._lc = np.sqrt(const.epSi * self.xj / self.cox)
        self._lmin = self.ns * self._leff / 10.
        self._Cox = self.cox * self.np * self._weff * self.ns * self._leff

        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)
Beispiel #35
0
        def process_params(self, thermal=False):
            # Remove tape if present
            ad.delete_tape(self)

            # Remove internal terminals (there should be none created
            # by intrinsic model)
            self.clean_internal_terms()
            # Tell autothermal (if used) to re-generate thermal ports
            self.__addThermalPorts = True

            # By default drain and source are terminals 0 and 2
            self.__di = 0
            self.__si = 2

            # Resistances
            extraVCCS = list()
            if self.rsh != 0.:
                if self.nrd != 0.:
                    # Drain resistor
                    self.__di = self.add_internal_term('di', 'V')
                    extraVCCS += [((0, self.__di), (0, self.__di),
                                   1. / self.rsh / self.nrd)]
                if self.nrs != 0.:
                    # Source resistor
                    self.__si = self.add_internal_term('si', 'V')
                    extraVCCS += [((2, self.__si), (2, self.__si),
                                   1. / self.rsh / self.nrs)]
            # Linear capacitances
            extraVCQS = list()
            if self.cgdo != 0.:
                # Gate-drain ovelrlap cap
                extraVCQS += [((1, self.__di), (1, self.__di),
                               self.cgdo * self.w)]
            if self.cgso != 0.:
                # Gate-source ovelrlap cap
                extraVCQS += [((1, self.__si), (1, self.__si),
                               self.cgso * self.w)]
            if self.cgbo != 0.:
                # Gate-bulk ovelrlap cap
                extraVCQS += [((1, 3), (1, 3), self.cgbo * self.l)]

            # Add extra linear resistors/caps (if any)
            self.linearVCCS = extraVCCS
            self.linearVCQS = extraVCQS

            # Override nonlinear port specs if needed
            if extraVCCS:
                # Ids, Idb, Isb
                self.csOutPorts = [(self.__di, self.__si), (self.__di, 3),
                                   (self.__si, 3)]
                # Controling voltages are DB, GB and SB
                self.controlPorts = [(self.__di, 3), (1, 3), (self.__si, 3)]
                # One charge source connected to each D, G, S
                self.qsOutPorts = [(self.__di, 3), (1, 3), (self.__si, 3)]

            # Calculate some variables (that may also be calculated in
            # intrinsic model)
            self.__Tnabs = const.T0 + self.tnom
            self.__egapn = self.eg0 - .000702 * (self.__Tnabs**2) \
                / (self.__Tnabs + 1108.)
            # Initialize variables in junctions
            if self.ad != 0.:
                self.dj = Junction()
                self.dj.process_params(isat=self.js * self.ad,
                                       cj0=self.cj * self.ad,
                                       vj=self.pb,
                                       m=self.mj,
                                       n=1.,
                                       fc=self.fc,
                                       xti=self.xti,
                                       eg0=self.eg0,
                                       Tnomabs=self.__Tnabs)
            if self.asrc != 0.:
                self.sj = Junction()
                self.sj.process_params(isat=self.js * self.asrc,
                                       cj0=self.cj * self.asrc,
                                       vj=self.pb,
                                       m=self.mj,
                                       n=1.,
                                       fc=self.fc,
                                       xti=self.xti,
                                       eg0=self.eg0,
                                       Tnomabs=self.__Tnabs)
            if self.pd != 0.:
                self.djsw = Junction()
                self.djsw.process_params(isat=self.jssw * self.pd,
                                         cj0=self.cjsw * self.pd,
                                         vj=self.pbsw,
                                         m=self.mjsw,
                                         n=1.,
                                         fc=self.fc,
                                         xti=self.xti,
                                         eg0=self.eg0,
                                         Tnomabs=self.__Tnabs)
            if self.ps != 0.:
                self.sjsw = Junction()
                self.sjsw.process_params(isat=self.jssw * self.ps,
                                         cj0=self.cjsw * self.ps,
                                         vj=self.pbsw,
                                         m=self.mjsw,
                                         n=1.,
                                         fc=self.fc,
                                         xti=self.xti,
                                         eg0=self.eg0,
                                         Tnomabs=self.__Tnabs)

            # Process parameters from intrinsic device:
            # set_temp_vars() called there
            IMOS.process_params(self)
Beispiel #36
0
        def process_params(self, thermal = False):
            # Remove tape if present
            ad.delete_tape(self)

            # Remove internal terminals (there should be none created
            # by intrinsic model)
            self.clean_internal_terms()
            # Tell autothermal (if used) to re-generate thermal ports
            self.__addThermalPorts = True

            # By default drain and source are terminals 0 and 2
            self.__di = 0
            self.__si = 2

            # Resistances
            extraVCCS = list()
            if self.rsh:
                if self.nrd:
                    # Drain resistor
                    self.__di = self.add_internal_term('di', 'V')
                    extraVCCS += [((0, self.__di), (0, self.__di), 
                                   1. / self.rsh / self.nrd)]
                if self.nrs:
                    # Source resistor
                    self.__si = self.add_internal_term('si', 'V')
                    extraVCCS += [((2, self.__si), (2, self.__si), 
                                   1. / self.rsh / self.nrs)]
            # Linear capacitances
            extraVCQS = list()
            if self.cgdo:
                # Gate-drain ovelrlap cap
                extraVCQS += [((1, self.__di), (1, self.__di),
                               self.cgdo * self.w)]
            if self.cgso:
                # Gate-source ovelrlap cap
                extraVCQS += [((1, self.__si), (1, self.__si),
                               self.cgso * self.w)]
            if self.cgbo:
                # Gate-bulk ovelrlap cap
                extraVCQS += [((1, 3), (1, 3),
                               self.cgbo * self.l)]

            # Add extra linear resistors/caps (if any)
            self.linearVCCS = extraVCCS
            self.linearVCQS = extraVCQS

            # Override nonlinear port specs if needed
            if extraVCCS:
                # Ids, Idb, Isb
                self.csOutPorts = [(self.__di, self.__si), (self.__di, 3), 
                                   (self.__si, 3)]
                # Controling voltages are DB, GB and SB
                self.controlPorts = [(self.__di, 3), (1, 3), (self.__si, 3)]
                # One charge source connected to each D, G, S
                self.qsOutPorts = [(self.__di, 3), (1, 3), (self.__si, 3)]

            # Calculate some variables (that may also be calculated in
            # intrinsic model)
            self.__Tnabs = const.T0 + self.tnom
            self.__egapn = self.eg0 - .000702 * (self.__Tnabs**2) \
                / (self.__Tnabs + 1108.)
            # Initialize variables in junctions
            if self.ad:
                self.dj = Junction()
                self.dj.process_params(isat = self.js * self.ad, 
                                       cj0 = self.cj * self.ad, 
                                       vj = self.pb, m = self.mj, 
                                       n = 1., fc = self.fc, 
                                       xti = self.xti, eg0 = self.eg0, 
                                       Tnomabs = self.__Tnabs)
            if self.asrc:
                self.sj = Junction()
                self.sj.process_params(isat = self.js * self.asrc, 
                                       cj0 = self.cj * self.asrc, 
                                       vj = self.pb, m = self.mj, 
                                       n = 1., fc = self.fc, 
                                       xti = self.xti, eg0 = self.eg0, 
                                       Tnomabs = self.__Tnabs)
            if self.pd:
                self.djsw = Junction()
                self.djsw.process_params(isat = self.jssw * self.pd, 
                                         cj0 = self.cjsw * self.pd, 
                                         vj = self.pbsw, m = self.mjsw, 
                                         n = 1., fc = self.fc, 
                                         xti = self.xti, eg0 = self.eg0, 
                                         Tnomabs = self.__Tnabs)
            if self.ps:
                self.sjsw = Junction()
                self.sjsw.process_params(isat = self.jssw * self.ps, 
                                         cj0 = self.cjsw * self.ps, 
                                         vj = self.pbsw, m = self.mjsw, 
                                         n = 1., fc = self.fc, 
                                         xti = self.xti, eg0 = self.eg0, 
                                         Tnomabs = self.__Tnabs)

            # Process parameters from intrinsic device:
            # set_temp_vars() called there
            IMOS.process_params(self)
Beispiel #37
0
        def process_params(self, thermal=False):
            # Remove tape if present
            ad.delete_tape(self)

            if thermal:
                extraTerms = 2
            else:
                extraTerms = 0

            # First check external connections
            if self.numTerms == 3 + extraTerms:
                self.__addCBjtn = False
            elif self.numTerms == 4 + extraTerms:
                self.__addCBjtn = True
            else:
                raise cir.CircuitError('{0}: Wrong number of connections. \
Can only be {1} or {2}, {3} found.'.format(self.instanceName, 3 + extraTerms,
                                           4 + extraTerms, self.numTerms))

            # Remove internal terminals
            self.clean_internal_terms()
            # Tell autothermal to re-generate thermal ports
            self.__addThermalPorts = True

            extraVCCS = list()
            if self.re != None:
                # Add et node and translate port descriptions
                self._et = self.add_internal_term('et', 'V')
                extraVCCS += [((2, self._et), (2, self._et),
                               self.area / self.re)]
            if self.rc != None:
                # Add ct node and translate port descriptions
                self._ct = self.add_internal_term('ct', 'V')
                extraVCCS += [((0, self._ct), (0, self._ct),
                               self.area / self.rc)]

            # Process parameters from intrinsic device: emitter and
            # collector terminals are already substituted.
            IBJT.process_params(self)
            # Calculate variables in junction
            self.cbjtn.process_params(self.iss, self.ns, self.fc, self.cjs,
                                      self.vjs, self.mjs, self.xti, self.eg,
                                      self.Tnomabs)
            # Add RE, RC resistors (if any)
            self.linearVCCS += extraVCCS
            if self.__addCBjtn:
                # Add bulk-collector junction
                self.__bccn = len(self.controlPorts)
                self.__bcon = len(self.csOutPorts)
                self.controlPorts.append((3, self._ct))
                self.csOutPorts.append((3, self._ct))
                if self.cjs != 0.:
                    self.qsOutPorts.append((3, self._ct))

                # Initial guess for input ports:
                try:
                    if len(self.vPortGuess) < len(self.controlPorts):
                        self.vPortGuess = np.concatenate(
                            (self.vPortGuess, [1]), axis=0)
                except AttributeError:
                    # Ignore if vPortGuess not provided
                    pass

            # Adjust temperature
            self.set_temp_vars(self.temp)
Beispiel #38
0
    def process_params(self, thermal = False):
        # Called once the external terminals have been connected and
        # the non-default parameters have been set. Make sanity checks
        # here. Internal terminals/devices should also be defined
        # here.  Raise cir.CircuitError if a fatal error is found.
        ad.delete_tape(self)
        if self.type == 'n':
            self._tf = 1.
        elif self.type == 'p':
            self._tf = -1.
            # Change parameter default values
            if not self.is_set('u0'):
                self.u0 = 250
        else:
            raise cir.CircuitError(
                '{0}: unrecognized type: {1}. Valid types are "n" or "p"'.format(self.nodeName, self.type))

        # Nominal abs temperature
        self._Tn = const.T0 + self.tnom
        # Nominal Thermal voltage
        self._Vtn = const.k * self._Tn / const.q

        self.factor1 = np.sqrt(const.epSi / const.epOx * self.tox)
        Eg0 = 1.16 - 7.02e-4 * (self._Tn**2) / (self._Tn + 1108.0)
        ni = 1.45e10 * (self._Tn / 300.15) * np.sqrt(self._Tn / 300.15) \
            * np.exp(21.5565981 - Eg0 / (2. * self._Vtn))
        #self.esi = 11.7 * const.epsilon0 (replaced by const.epSi)
        self.ldrn = self.l
        self.wdrn = self.w
        
        t0 = pow(self.ldrn, self.lln)
        t1 = pow(self.wdrn, self.lwn)
        tmp1 = self.ll / t0 + self.lw / t1 + self.lwl / (t0 * t1)
        self.dl = self.lint + tmp1
        #tmp2 = llc / t0 + lwc / t1 + lwlc / (t0 * t1)
        #self.dlc = dlc + tmp2  # ???
        
        t2 = pow(self.ldrn, self.wln)
        t3 = pow(self.wdrn, self.wwn)
        tmp3 = self.wl / t2 + self.ww / t3 + self.wwl / (t2 * t3)
        self.dw = self.wint + tmp3
        #tmp4 = wlc / t2 + wwc / t3 + wwlc / (t2 * t3)
        #self.dwc = dwc + tmp4 # ???
        
        self.leff = self.l - 2.0 * self.dl
        self.weff = self.w - 2.0 * self.dw

        self.AbulkCVfactor = (1. + pow(self.clc/self.leff, self.cle))

        #self.leffCV = l - 2.0 * dlc
        #self.t11 = leffCV * leffCV

        # was epOx = 3.453133e-11
        self.cox = const.epOx / self.tox

        self.phi = 2. * self._Vtn * np.log(self.nch / ni)
        self.sqrtPhi = np.sqrt(self.phi)
        self.phis3 = self.sqrtPhi * self.phi

        self.Xdep0 = np.sqrt(2. * const.epSi / 
                          (const.q * self.nch * 1e6)) * self.sqrtPhi
        self.litl = np.sqrt(3. * self.xj * self.tox)
        self.vbi = self._Vtn * np.log(1.0e20 * self.nch / (ni**2))
        self.cdep0 = np.sqrt(const.q * const.epSi * self.nch * 1e6 
                          / 2. / self.phi)

        if not self.is_set('toxm'):
            self.toxm = self.tox
        if not self.is_set('dsub'):
            self.dsub = self.drout

        self.ldeb = np.sqrt(const.epSi * self._Vtn
                           / (const.q * self.nch * 1e6)) / 3.
        
        #import pdb; pdb.set_trace()
        if self.k1enable and not (self.is_set('k1') or self.is_set('k2')):
            vbx = self.phi - 7.7348e-4  * self.nch * self.xt**2
            # From ngspice
            vbx = -abs(vbx)
            Vbm = -abs(self.vbm)
            gamma1 = 5.753e-12 * np.sqrt(self.nch) / self.cox
            gamma2 = 5.753e-12 * np.sqrt(self.nsub) / self.cox
            T0 = gamma1 - gamma2
            T1 = np.sqrt(self.phi - vbx) - self.sqrtPhi
            T2 = np.sqrt(self.phi * (self.phi - Vbm)) - self.phi
            self._k2 = T0 * T1 / (2. * T2 + Vbm)
            self._k1 = gamma2 - 2. * self._k2 * np.sqrt(self.phi - Vbm)
            # print self._k1, self._k2
        else:
            self._k1 = self.k1
            self._k2 = self.k2
        
        if not self.is_set('vth0'):
            self._vth0 = self.vfb + self.phi + self._k1 * self.sqrtPhi
        else:
            self._vth0 = abs(self.vth0)

        self.k1ox = self._k1 * self.tox / self.toxm
        self.k2ox = self._k2 * self.tox / self.toxm

        t1 = np.sqrt(const.epSi / const.epOx * self.tox * self.Xdep0)
        t0 = ad.safe_exp(-0.5 * self.dsub * self.leff / t1)
        self.theta0vb0 = (t0 + 2.0 * t0**2)
        # From freeda, ngspice:
        self._Tox = 1e8 * self.tox
        
        #Calculation of vbsc(Vbc) and Vbseff
        if self._k2 < 0.:
            self.vbsc = .9 * (self.phi - (.5 * self._k1 / self._k2)**2)
            if self.vbsc > -3.:
                self.vbsc = -3.
            elif self.vbsc < -30.:
                self.vbsc = -30.
        else:
            self.vbsc = -30.

        if self.u0 > 1.:
            self._u0 = self.u0 * 1e-4
        else:
            self._u0 = self.u0 

        if not thermal:
            # Calculate temperature-dependent variables
            self.set_temp_vars(self.temp)