import matplotlib from glob import glob rc('text', usetex=True) font = {'family' : 'sans-serif', 'weight' : 'bold', 'size' : 18} rc('font', **font) allvbgs = np.empty((3,400)) for i, temp in enumerate(['0', '27', '70']): fig = plt.figure(i) fig.tight_layout() runs = glob('../sims/tbtran_tt_mm_1_mc_1_{}degc_run_[0-9]*.raw'.format(temp)) runs2 = [x for x in runs if 'randomseed' not in x] vbgs = [np.asarray(s3r.read(run)['v(vbg)']) for run in runs2] vbgfinals = [vbg.flatten()[-1]*1.0e3 for vbg in vbgs] #in mV allvbgs[i]=(vbgfinals) mean = np.mean(vbgfinals) stdev = np.std(vbgfinals) hist = np.histogram(vbgfinals) plt.hist(vbgfinals, bins='auto',ec='black') plt.xticks(fontsize=18) plt.yticks(fontsize=18) plt.grid(True) plt.xlabel(r"$V_{out}$ (mV)") plt.ylabel(r"Sample Count") plt.title("Monte Carlo Simulation on Reference Voltage" "\n" "temp = ${}^\circ$C" "\n"
sys.path.append('/tmp/kustinj/ee272b/pyMOSChar') import spice3read as s3r import numpy as np import matplotlib.lines as mlines import matplotlib.pyplot as plt from scipy import constants import model_bgvr q = constants.e k = constants.k xVar = 'temp-sweep' yVar = 'v(e2)' dVar = 'v(deriv(e2))' plotDat = s3r.read( '/home/users/kustinj/.xschem/simulations/bipolar_char_temp_vbe_current_3p40.raw' ) current = np.arange(0.1156, 115.6, 0.1) # in units of uA dVbe = plotDat[dVar] steadiestdVbes = np.std(dVbe, axis=1) mostConstantdVbe = np.argmin( np.abs(steadiestdVbes )) # choose most constant dVbe to have easiest TC cancellation T = plotDat[xVar] targI = mostConstantdVbe #16.4 # indx = (np.abs(current - targI)).argmin( ) # https://philbull.wordpress.com/2012/01/11/numpy-tip-getting-index-of-an-array-element-nearest-to-some-value/ # interp Vbe to find its value when T=27degC VbeNominal = np.interp(27, plotDat[xVar][indx], plotDat[yVar][indx]) print('interpolated Vbe at 27degC: {} mV'.format(VbeNominal * 1e3))
import sys sys.path.append('/tmp/kustinj/ee272b/pyMOSChar') import spice3read as s3r import matplotlib.pyplot as plt import os from glob import glob import numpy as np import matplotlib plotDat = [] for fname in glob('*.raw'): plotDat.append( (s3r.read(fname), fname.strip('.raw').replace('tsmc_bandgap_', ''))) xvar = 'temp-sweep' yvar = 'v(vbg)' matplotlib.rc('xtick', labelsize=15) matplotlib.rc('ytick', labelsize=15) for x in plotDat: data = x[0] lab = x[1] upperx = np.where(data[xvar][0] >= 0.) lowerx = np.where(data[xvar][0] <= 70.) rangex = np.intersect1d(upperx, lowerx) xdat = data[xvar][0][rangex] ydat = data[yvar][0][rangex] plt.plot(xdat, ydat * 1e3, label=lab) plt.grid() plt.legend() plt.xlabel('Temperature (degC)') plt.ylabel('Vref (mV)')
import sys sys.path.append('../pyMOSChar') import spice3read as s3r import numpy as np opdat = s3r.read('../sims/tsmc_bandgap_real_op.raw') gms = [entry for entry in opdat.keys() if '[gm]' in entry] ids = [entry for entry in opdat.keys() if '[id]' in entry] ids.remove('i(@m.xm10.msky130_fd_pr__nfet_01v8_lvt[id])') gms.sort() ids.sort() vdsats = [] for i, x in enumerate(gms): gm = opdat[x] id = opdat[ids[i]] vdsats.append(2 / (gm / id)) indx = range(1, 10) indx.insert(1, 13) vdsats = np.asarray(vdsats).flatten() print('vdsats') for i, n in enumerate(indx): print('vdsat{} = {}'.format(n, vdsats[i])) vdd = opdat['v(vdd)'] va = opdat['v(va)'] vb = opdat['v(vb)'] vbg = opdat['v(vbg)'] vgate = opdat['v(vgate)'] vq = opdat['v(vq)']
import sys sys.path.append('../pyMOSChar') import spice3read as s3r import numpy as np import matplotlib.pyplot as plt from matplotlib import rc from scipy import interpolate rc('text', usetex=True) font = {'family': 'sans-serif', 'weight': 'bold', 'size': 14} rc('font', **font) for i, corner in enumerate(['tt', 'ss', 'ff']): tran27 = s3r.read('../sims/tbtran_{}_mm_0_27degc_vbg.raw'.format(corner)) tran0 = s3r.read('../sims/tbtran_{}_mm_0_0degc_vbg.raw'.format(corner)) tran70 = s3r.read('../sims/tbtran_{}_mm_0_70degc_vbg.raw'.format(corner)) randomseed = np.asarray( s3r.read('../sims/tbtran_{}_mm_0_randomseed.raw'.format(corner)) ['randomseed']).flatten()[0] vbg27 = tran27['v(vbg)'][0][-1] vbg0 = tran0['v(vbg)'][0][-1] vbg70 = tran70['v(vbg)'][0][-1] idleTime = 4.0e-6 ppm = (vbg70 - vbg0) / vbg27 / 70 * 1e6 print('0, 27, 70 degC') print('{} {} {}'.format(vbg0, vbg27, vbg70)) print(ppm) times = [tran0['time'][0], tran27['time'][0], tran70['time'][0]] maxtime = times[np.asarray([len(x) for x in times]).argmax()] tranvbg27 = np.interp(maxtime, times[1], tran27['v(vbg)'][0]) tranvbg0 = np.interp(maxtime, times[0], tran0['v(vbg)'][0])
import sys sys.path.append('../pyMOSChar') import spice3read as s3r import matplotlib.pyplot as plt import numpy as np import matplotlib.lines as mlines import matplotlib matplotlib.rc('xtick',labelsize=15) matplotlib.rc('ytick',labelsize=15) plotDat = s3r.read('../sims/bipolar_char_temp_vbe_current_3p40.raw') current = np.arange(0.01,146,step=20) # in units of uA fig, ax1 = plt.subplots(1) ax1.set_xlabel('Temp (degC)') ax1.set_ylabel('Veb (V)') ax1.set_title('PNP CTAT Behavior') xVar = 'temp-sweep' yVar = 'v(e2)' zVar = 'i(v1)' ax1.grid() lns = [] colors = [] for i in range(np.shape(plotDat[xVar])[0]): lns.append(ax1.plot(plotDat[xVar][i], plotDat[yVar][i], label=np.format_float_scientific(current[i], precision=3))) colors.append(lns[i][0].get_c()) #print(np.format_float_scientific(current[i],precision=3)) labs = [l[0].get_label() for l in lns] lg1 = ax1.legend(labs, loc=3, title='Ic (uA)', prop={'size':15}) lg1.get_title().set_fontsize(15) dT = plotDat[xVar][0][1] - plotDat[xVar][0][0] dVbe = [np.gradient(plotDat[yVar][i], dT)*1E3 for i in range(np.shape(plotDat[xVar])[0])]
biascurrent = current / 5 activeloadwidth = (biascurrent / 2) / JDpmos[activeloadgmindex] print('activeloadwidth {}'.format(activeloadwidth)) nmoscurrentmirrorwidth = biascurrent / JDnmos[gmidnmosof20index] print('nmoscurrentmirrorwidth {}'.format(nmoscurrentmirrorwidth)) nmosamplifierwidth = (biascurrent / 2) / JDnmos[gmidnmosof25index] print('nmosamplifierwidth {}'.format(nmosamplifierwidth)) if os.path.exists( '/home/users/kustinj/.xschem/simulations/tsmc_bandgap_real.raw'): print('sim results') opdat = s3r.read( '/home/users/kustinj/.xschem/simulations/tsmc_bandgap_real.raw') gms = [entry for entry in opdat.keys() if '[gm]' in entry] ids = [entry for entry in opdat.keys() if '[id]' in entry] ids.remove('i(@m.xm10.msky130_fd_pr__nfet_01v8_lvt[id])') gms.sort() ids.sort() gmids = np.asarray([opdat[gm] / opdat[ids[i]] for i, gm in enumerate(gms)]).flatten() vdsats = [] for i, x in enumerate(gms): gm = opdat[x] id = opdat[ids[i]] vdsats.append(2 / (gm / id)) gmidm1 = gmids[0]
def genDB(): if (simulator == "ngspice"): genNetlistNngspice() genNetlistPngspice() elif (simulator == "spectre"): genNetlistSpectre() else: print "ERROR: Invalid/Unsupported simulator specified" sys.exit(0) progTotal = len(mosLengths) * len(vsb) progCurr = 0 print("Data generation in progress. Go have a coffee...") for idxL in range(len(mosLengths)): for idxVSB in range(len(vsb)): if (simulator == "ngspice"): genSimParams(mosLengths[idxL], vsb[idxVSB]) myfile = open("charMOSpy.log", "a") myfile.write("charMOS: Simulating for L={0}, VSB={1}\n".format( idxL, idxVSB)) myfile.close() runSim("charNMOS.net", "ngspice") simDat = spice3read.read('outN.raw') mosDat['nfet']['id'][idxL][idxVSB] = simDat['i(id)'] mosDat['nfet']['vt'][idxL][idxVSB] = simDat['vt'] mosDat['nfet']['gm'][idxL][idxVSB] = simDat['gm'] mosDat['nfet']['gmb'][idxL][idxVSB] = simDat['gmb'] mosDat['nfet']['gds'][idxL][idxVSB] = simDat['gds'] mosDat['nfet']['cgg'][idxL][idxVSB] = simDat['cgg'] mosDat['nfet']['cgs'][idxL][idxVSB] = simDat['cgs'] mosDat['nfet']['cgd'][idxL][idxVSB] = simDat['cgd'] mosDat['nfet']['cgb'][idxL][idxVSB] = simDat['cgb'] mosDat['nfet']['cdd'][idxL][idxVSB] = simDat['cdd'] mosDat['nfet']['css'][idxL][idxVSB] = simDat['css'] runSim("charPMOS.net", "ngspice") simDat = spice3read.read('outP.raw') mosDat['pfet']['id'][idxL][idxVSB] = simDat['i(id)'] mosDat['pfet']['vt'][idxL][idxVSB] = simDat['vt'] mosDat['pfet']['gm'][idxL][idxVSB] = simDat['gm'] mosDat['pfet']['gmb'][idxL][idxVSB] = simDat['gmb'] mosDat['pfet']['gds'][idxL][idxVSB] = simDat['gds'] mosDat['pfet']['cgg'][idxL][idxVSB] = simDat['cgg'] mosDat['pfet']['cgs'][idxL][idxVSB] = simDat['cgs'] mosDat['pfet']['cgd'][idxL][idxVSB] = simDat['cgd'] mosDat['pfet']['cgb'][idxL][idxVSB] = simDat['cgb'] mosDat['pfet']['cdd'][idxL][idxVSB] = simDat['cdd'] mosDat['pfet']['css'][idxL][idxVSB] = simDat['css'] elif (simulator == "spectre"): genSimParamsSpectre(mosLengths[idxL], vsb[idxVSB]) runSim("charMOS.scs", "spectre") simDat = spice3read.read('charMOS.raw', 'spectre') if (subcktPath == ""): nmos = "mn" pmos = "mp" else: nmos = "mn." + subcktPath pmos = "mp." + subcktPath mosDat['nfet']['id'][idxL][idxVSB] = simDat['{0}:ids'.format( nmos)] mosDat['nfet']['vt'][idxL][idxVSB] = simDat['{0}:vth'.format( nmos)] mosDat['nfet']['gm'][idxL][idxVSB] = simDat['{0}:gm'.format( nmos)] mosDat['nfet']['gmb'][idxL][idxVSB] = simDat['{0}:gmbs'.format( nmos)] mosDat['nfet']['gds'][idxL][idxVSB] = simDat['{0}:gds'.format( nmos)] mosDat['nfet']['cgg'][idxL][idxVSB] = simDat['{0}:cgg'.format( nmos)] mosDat['nfet']['cgs'][idxL][idxVSB] = simDat['{0}:cgs'.format( nmos)] mosDat['nfet']['cgd'][idxL][idxVSB] = simDat['{0}:cgd'.format( nmos)] mosDat['nfet']['cgb'][idxL][idxVSB] = simDat['{0}:cgb'.format( nmos)] mosDat['nfet']['cdd'][idxL][idxVSB] = simDat['{0}:cdd'.format( nmos)] mosDat['nfet']['css'][idxL][idxVSB] = simDat['{0}:css'.format( nmos)] mosDat['pfet']['id'][idxL][idxVSB] = simDat['{0}:ids'.format( pmos)] mosDat['pfet']['vt'][idxL][idxVSB] = simDat['{0}:vth'.format( pmos)] mosDat['pfet']['gm'][idxL][idxVSB] = simDat['{0}:gm'.format( pmos)] mosDat['pfet']['gmb'][idxL][idxVSB] = simDat['{0}:gmbs'.format( pmos)] mosDat['pfet']['gds'][idxL][idxVSB] = simDat['{0}:gds'.format( pmos)] mosDat['pfet']['cgg'][idxL][idxVSB] = simDat['{0}:cgg'.format( pmos)] mosDat['pfet']['cgs'][idxL][idxVSB] = simDat['{0}:cgs'.format( pmos)] mosDat['pfet']['cgd'][idxL][idxVSB] = simDat['{0}:cgd'.format( pmos)] mosDat['pfet']['cgb'][idxL][idxVSB] = simDat['{0}:cgb'.format( pmos)] mosDat['pfet']['cdd'][idxL][idxVSB] = simDat['{0}:cdd'.format( pmos)] mosDat['pfet']['css'][idxL][idxVSB] = simDat['{0}:css'.format( pmos)] rows, columns = os.popen('stty size', 'r').read().split() columns = int(columns) - 10 progCurr += 1 progPercent = 100 * progCurr / progTotal progLen = int(progPercent * columns / 100) sys.stdout.write("\r[{0}{1}] {2}%".format( "#" * progLen, " " * (columns - progLen), progPercent)) sys.stdout.flush() os.system( 'rm -fr charNMOS.net charPMOS.net simParams.net outN.raw outP.raw b3v33check.log charMOS.scs simParams.scs charMOS.raw charMOS.raw.psf charMOS.ahdlSimDB charMOS.log' ) print print("Data generated. Saving...") pickle.dump(mosDat, open(datFileName, "wb"), pickle.HIGHEST_PROTOCOL) print("Done! Data saved in " + datFileName)
import sys sys.path.append('../pyMOSChar') import spice3read as s3r import numpy as np import matplotlib.pyplot as plt from matplotlib import rc rc('text', usetex=True) rc('font', family='serif') data = s3r.read('../sims/tsmc_bandgap_real_tempsweep.raw') vbg = data['v(vbg)'][0] temp = data['temp-sweep'][0] vbg0 = np.interp(0, temp, vbg) vbg27 = np.interp(27, temp, vbg) vbg70 = np.interp(70, temp, vbg) ppm = (vbg70-vbg0)/vbg27/70*1e6 fig, ax = plt.subplots() ax.plot(temp, vbg) ax.plot(0, vbg0, '-bo', label='{} mV'.format(np.around(vbg0*1e3,3))) ax.plot(27, vbg27, '-ro', label='{} mV'.format(np.around(vbg27*1e3,3))) ax.plot(70, vbg70, '-yo', label='{} mV'.format(np.around(vbg70*1e3, ))) ax.grid() ax.set_title('DC Temperature Sweep. Vref = {} mV. ppm = {}'.format(np.around(vbg27*1e3, 3), np.around(ppm, 3))) ax.set_xlabel("Temperature $^\circ$C") ax.set_ylabel('Vout (V)') ax.legend() plt.show()