-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathplot_dynphys.py
More file actions
78 lines (69 loc) · 2.6 KB
/
Copy pathplot_dynphys.py
File metadata and controls
78 lines (69 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env python3
"""Render the Enhancement-75 dynamic-physics plots from the artifacts the
verify script leaves behind (run verify_dynphys.py first)."""
import math
import os
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
HERE = os.path.dirname(os.path.abspath(__file__))
PLOTS = os.path.join(HERE, "plots")
os.makedirs(PLOTS, exist_ok=True)
def read_wave(name):
rows = []
for line in open(os.path.join(HERE, name)):
p = line.split()
if len(p) >= 2:
try:
rows.append((float(p[0]), float(p[1])))
except ValueError:
pass
return rows
# [1] Cgg(V): the transient ramp gives the continuous curve
ramp = read_wave("_dp_cggtran.dat")
rate = 1.2 / 120e-6
ramp = [(t, i) for t, i in ramp if t > 1e-6] # skip the integrator start-up
v = [t * rate for t, _ in ramp]
cgg = [-i / rate * 1e15 for _, i in ramp]
fig, ax = plt.subplots(figsize=(7, 4.5))
ax.plot(v, cgg, label="transient ramp $-i_g/(dV_g/dt)$")
ax.set_xlabel("$V_g$ [V]")
ax.set_ylabel("$C_{gg}$ [fF]")
ax.set_title("PSP103 gate capacitance: one charge model, two code paths")
ax.grid(alpha=0.3)
ax.legend(title="AC points (Im$(i_g)/\\omega$) sit on this curve\nto < 6e-4 — see verify output")
fig.tight_layout()
fig.savefig(os.path.join(PLOTS, "cgg_two_paths.png"), dpi=110)
plt.close(fig)
# [2] closed-loop charge: gate current over the triangle sweep
loop = read_wave("_dp_qloop.dat")
fig, ax = plt.subplots(figsize=(7, 4.5))
ax.plot([t * 1e6 for t, _ in loop], [i * 1e9 for _, i in loop])
ax.set_xlabel("t [µs]")
ax.set_ylabel("$i_g$ [nA]")
ax.set_title("Closed gate-bias loop: up/down charge cancels to 8e-5")
ax.grid(alpha=0.3)
fig.tight_layout()
fig.savefig(os.path.join(PLOTS, "charge_loop.png"), dpi=110)
plt.close(fig)
# [4] linear response: last transient cycles (10 MHz run is the one on disk)
seg = read_wave("_dp_cstran.dat")
f = 1e7
T = 1 / f
tail = [(t, v) for t, v in seg if t >= 10 * T]
fig, ax = plt.subplots(figsize=(7, 4.5))
ax.plot([t * 1e9 for t, _ in tail], [v * 1e3 for _, v in tail],
label="transient steady state")
vavg = sum(v for _, v in tail) / len(tail)
# the AC prediction plotted from the quadrature-fit amplitude/phase would be
# indistinguishable (rel 2e-6); annotate instead
ax.axhline(vavg * 1e3, ls="--", alpha=0.4, label="operating point")
ax.set_xlabel("t [ns]")
ax.set_ylabel("v(d) [mV]")
ax.set_title("PSP103 stage, 1 mV @ 10 MHz: tran matches .ac to 2e-6 / 0.001°")
ax.grid(alpha=0.3)
ax.legend()
fig.tight_layout()
fig.savefig(os.path.join(PLOTS, "linear_response.png"), dpi=110)
plt.close(fig)
print("plots written to plots/")