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)
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.
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
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
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)
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)
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)
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
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)
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
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)
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)]
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)
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)
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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)