Update process script to generate TeX.

This commit is contained in:
Danila Fedorin 2021-01-27 15:04:23 -08:00
parent 1ca79fc52b
commit a55e55f04f
2 changed files with 101 additions and 7 deletions

66
Lab2/lab2.tex Normal file
View File

@ -0,0 +1,66 @@
\documentclass{article}
\usepackage[margin=1in]{geometry}
\usepackage{amsmath}
\usepackage{graphicx}
\begin{document}
\section*{Lab 2}
The data gathered in this lab is listed in tables
1 and 2.
\begin{figure}[h]
\centering
\begin{tabular}{lcccccc}
Node & $g_m$ (S) & $r_o$ ($\Omega$) & Gain & $I_\text{off} (A)$ & $I_\text{on} (A)$ & $I_\text{on}/I_\text{off}$ \\
\hline
longchannel pmos & 4.01E-04 & 1.36E+04 & 5.457 & 1.02E-11 & 1.36E-03 & 1.34E+08 \\
longchannel nmos & 9.13E-04 & 1.31E+04 & 11.95 & 1.12E-11 & 3.22E-03 & 2.87E+08 \\
50nm pmos & 2.11E-04 & 1.55E+04 & 3.259 & 8.84E-09 & 1.48E-04 & 1.68E+04 \\
50nm nmos & 4.44E-04 & 1.31E+04 & 5.793 & 3.64E-09 & 3.12E-04 & 8.55E+04 \\
16nmlp pmos & 1.62E-04 & 1.68E+04 & 2.72 & 2.30E-11 & 5.54E-05 & 2.40E+06 \\
16nmlp nmos & 2.88E-04 & 1.33E+04 & 3.83 & 8.87E-12 & 9.13E-05 & 1.03E+07 \\
16nmhp pmos & 3.33E-04 & 5.37E+03 & 1.787 & 9.22E-08 & 1.51E-04 & 1.64E+03 \\
16nmhp nmos & 4.95E-04 & 5.56E+03 & 2.755 & 7.41E-08 & 2.17E-04 & 2.93E+03 \\
\end{tabular}
\label{fig:dc}
\caption{Properties of various transistor sizes and types}
\end{figure}
\begin{figure}[h]
\centering
\begin{tabular}{lcccccc}
Node & Oscillation Period (ps) & Oscillation Frequency (GHz) \\
\hline
longchannel & 1020 & 0.980 \\
50nm & 222 & 4.49 \\
16nmlp & 140 & 7.11 \\
16nmhp & 32.2 & 31.0 \\
\end{tabular}
\label{fig:t}
\caption{Switching frequency of 5-long inverter loop.}
\end{figure}
From these tables, we can see that smaller transistors have progressively smaller
gain, and progressively smaller ratios of on current $I_\text{on}$ and off current
$I_\text{off}$. We can explain the drop in gain with velocity saturation. At smaller
scales, short-channel effects make the relationship between current and gate voltage no longer
quadratic, but linear (and thus smaller in magnitude). This means that the transconductance
of a transistor decreases as it gets smaller, leading to lower gain. Furthermore,
due to short-channel effects such as impact ionization, current doesn't stop increasing
past the theoretical saturation point. This makes the transistor behave less like
a current source past saturation, and decreases gain.
Decreasing the size of the transistor does, however, significantly improve its timing characteristics.
While at 1$\mu m$ the 5-transistor loop we simulated has an oscillation frequency of 0.98GHz, the 16nm
high power loop can go as fast as 31GHz. This is likely due to the decreased capacitances at
this scale: it takes less time to charge up any part of the CMOS logic, including the outputs,
which makes it possible for subsequent transistors to respond faster, and so on.
For analog circuits, we care about gain, since we want to ensure that our signal is transmitted
properly through our circuit. Thus, bigger transistors are probably better suited for this application,
since they have higher (sometimes much higher) gains than smaller transistors. On the other hand,
from the digital side, the gain doesn't matter as much as the performance characteristics of the transistor,
which makes the smaller nodes (ones that we measured to have higher oscillation frequency) preferable.
\end{document}

View File

@ -27,8 +27,8 @@ simulations = {
}
moss = {
"nmos": "M1 2 1 0 0 nmos W={10*ll} L= ll",
"pmos": "M1 2 1 vdd vdd pmos W={10*ll} L={ll}"
"pmos": "M1 2 1 vdd vdd pmos W={10*ll} L={ll}",
"nmos": "M1 2 1 0 0 nmos W={10*ll} L= ll"
}
script_dc = """
@ -96,16 +96,40 @@ def find_period(ident, script, model, mos, l):
group2.append((dp, time[i]))
peak1 = max(group1)[1] * 1000000000000
peak2 = max(group2)[1] * 1000000000000
print(ident, peak2-peak1)
print(ident, peak2-peak1, 1/(peak2-peak1) * 1000)
def find_table(ident, script, model, mos, l):
vds = l.get_data('vds')
current_lo = l.get_data('I(vds)', 0)
current_hi = l.get_data('I(vds)', l.case_count - 1)
if mos == "nmos":
vgs1 = l.get_data('I(vds)', l.case_count - 2)
vgs2 = l.get_data('I(vds)', l.case_count - 1)
gm = (vgs2[-1]-vgs1[-1])/(simulations[model][0]/12)
vds = l.get_data('vds', l.case_count - 1)
ids = l.get_data('I(vds)', l.case_count - 1)
ro = (vds[-5] - vds[-1])/(ids[-5] - ids[-1])
print("{} & {:.2E} & {:.2E} & {:.4} & {:.2E} & {:.2E} & {:.2E} \\\\".format(
ident[3:].replace("_", " "), -gm, -ro, gm * ro, -current_lo[-1], -current_hi[-1], current_hi[-1]/current_lo[-1]))
if mos == "pmos":
vgs1 = l.get_data('I(vds)', 0)
vgs2 = l.get_data('I(vds)', 1)
gm = (vgs2[0]-vgs1[0])/(simulations[model][0]/12)
vds = l.get_data('vds', 0)
ids = l.get_data('I(vds)', 0)
ro = (vds[50] - vds[0])/(ids[50] - ids[0])
print("{} & {:.2E} & {:.2E} & {:.4} & {:.2E} & {:.2E} & {:.2E} \\\\".format(
ident[3:].replace("_", " "), -gm, -ro, gm * ro, current_hi[0], current_lo[0], current_lo[0]/current_hi[0]))
def find_onoff(ident, script, model, mos, l):
vds = l.get_data('vds')
current_lo = l.get_data('I(vds)', 0)
current_hi = l.get_data('I(vds)', l.case_count - 1)
if mos == "nmos":
print(ident, -current_lo[-1] * 1000, -current_hi[-1] * 1000, current_hi[-1]/current_lo[-1])
print("node: {}\toff: {:.2E}\ton: {:.2E}\tratio: {:.2E}".format(ident, -current_lo[-1], -current_hi[-1], current_hi[-1]/current_lo[-1]))
if mos == "pmos":
print(ident, current_lo[0] * 1000, current_hi[0] * 1000, current_lo[0]/current_hi[0])
print("node: {}\toff: {:.2E}\ton: {:.2E}\tratio: {:.2E}".format(ident, current_hi[0], current_lo[0], current_lo[0]/current_hi[0]))
def find_gm(ident, script, model, mos, l):
vds = l.get_data('vds')
@ -154,6 +178,10 @@ def run_sim(script, model, mos, callback, file_type = "dc"):
callback(scriptname, script, model, mos, l)
print(" --- LaTeX --- ")
for node in simulations.keys():
for mos in moss.keys():
run_sim(script_dc, node, mos, find_table)
print(" --- gm, ro --- ")
for mos in moss.keys():
@ -161,8 +189,8 @@ for mos in moss.keys():
run_sim(script_dc, node, mos, find_gm)
print(" --- onoff --- ")
for mos in moss.keys():
for node in simulations.keys():
for mos in moss.keys():
run_sim(script_dc, node, mos, find_onoff)
print(" --- period --- ")