163 lines
4.6 KiB
Python
163 lines
4.6 KiB
Python
""" test OSDI simulation of diode
|
|
"""
|
|
import os, shutil
|
|
import numpy as np
|
|
import pandas as pd
|
|
import sys
|
|
sys.path.append(
|
|
os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
|
|
|
|
from testing import prepare_test
|
|
|
|
# This test runs a DC, AC and Transient Simulation of a simple diode.
|
|
# The diode is available in the "OSDI" Git project and needs to be compiled to a shared object
|
|
# and then bet put into /usr/local/share/ngspice/osdi:
|
|
#
|
|
# > make osdi_diode
|
|
# > cp diode_osdi.osdi /usr/local/share/ngspice/osdi/diode_osdi.osdi
|
|
#
|
|
# The integration test proves the functioning of the OSDI interface. The Ngspice diode is quite
|
|
# complicated and the results are therefore not exactly the same.
|
|
# Future tests will target Verilog-A models like HICUM/L2 that should yield exactly the same results as the Ngspice implementation.
|
|
|
|
directory = os.path.dirname(__file__)
|
|
|
|
|
|
def test_ngspice():
|
|
dir_osdi, dir_built_in = prepare_test(directory)
|
|
|
|
# read DC simulation results
|
|
dc_data_osdi = pd.read_csv(os.path.join(dir_osdi, "dc_sim.ngspice"), sep="\\s+")
|
|
dc_data_built_in = pd.read_csv(
|
|
os.path.join(dir_built_in, "dc_sim.ngspice"), sep="\\s+"
|
|
)
|
|
|
|
id_osdi = dc_data_osdi["i(vsense)"].to_numpy()
|
|
id_built_in = dc_data_built_in["i(vsense)"].to_numpy()
|
|
|
|
# read AC simulation results
|
|
ac_data_osdi = pd.read_csv(os.path.join(dir_osdi, "ac_sim.ngspice"), sep="\\s+")
|
|
ac_data_built_in = pd.read_csv(
|
|
os.path.join(dir_built_in, "ac_sim.ngspice"), sep="\\s+"
|
|
)
|
|
|
|
# read TR simulation results
|
|
tr_data_osdi = pd.read_csv(os.path.join(dir_osdi, "tr_sim.ngspice"), sep="\\s+")
|
|
tr_data_built_in = pd.read_csv(
|
|
os.path.join(dir_built_in, "tr_sim.ngspice"), sep="\\s+"
|
|
)
|
|
|
|
# test simulation results
|
|
id_osdi = dc_data_osdi["i(vsense)"].to_numpy()
|
|
id_built_in = dc_data_built_in["i(vsense)"].to_numpy()
|
|
np.testing.assert_allclose(id_osdi[20:40], id_built_in[20:40], rtol=0.03)
|
|
|
|
return (
|
|
dc_data_osdi,
|
|
dc_data_built_in,
|
|
ac_data_osdi,
|
|
ac_data_built_in,
|
|
tr_data_osdi,
|
|
tr_data_built_in,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
(
|
|
dc_data_osdi,
|
|
dc_data_built_in,
|
|
ac_data_osdi,
|
|
ac_data_built_in,
|
|
tr_data_osdi,
|
|
tr_data_built_in,
|
|
) = test_ngspice()
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
# DC Plot
|
|
pd_built_in = dc_data_built_in["v(d)"] * dc_data_built_in["i(vsense)"]
|
|
pd_osdi = dc_data_osdi["v(d)"] * dc_data_osdi["i(vsense)"]
|
|
fig, ax1 = plt.subplots()
|
|
ax2 = ax1.twinx()
|
|
ax1.semilogy(
|
|
dc_data_built_in["v(d)"],
|
|
dc_data_built_in["i(vsense)"] * 1e3,
|
|
label="built-in",
|
|
linestyle=" ",
|
|
marker="x",
|
|
)
|
|
ax1.semilogy(
|
|
dc_data_osdi["v(d)"],
|
|
dc_data_osdi["i(vsense)"] * 1e3,
|
|
label="OSDI",
|
|
)
|
|
ax2.plot(
|
|
dc_data_built_in["v(d)"],
|
|
dc_data_built_in["v(t)"],
|
|
label="built-in",
|
|
linestyle=" ",
|
|
marker="x",
|
|
)
|
|
ax2.plot(
|
|
dc_data_osdi["v(d)"],
|
|
dc_data_osdi["v(t)"],
|
|
label="OSDI",
|
|
)
|
|
ax1.set_ylabel(r"$I_{\mathrm{D}} (\mathrm{mA})$")
|
|
ax2.set_ylabel(r"$\Delta T_{\mathrm{j}}(\mathrm{K})$")
|
|
ax1.set_xlabel(r"$V_{\mathrm{D}}(\mathrm{V})$")
|
|
plt.legend()
|
|
|
|
# AC Plot
|
|
omega = 2 * np.pi * ac_data_osdi["frequency"]
|
|
fig = plt.figure()
|
|
plt.semilogx(
|
|
ac_data_built_in["frequency"],
|
|
ac_data_built_in["i(vsense)"] * 1e3,
|
|
label="built-in",
|
|
linestyle=" ",
|
|
marker="x",
|
|
)
|
|
plt.semilogx(
|
|
ac_data_osdi["frequency"], ac_data_osdi["i(vsense)"] * 1e3, label="OSDI"
|
|
)
|
|
plt.xlabel("$f(\\mathrm{H})$")
|
|
plt.ylabel("$\\Re \\left\{ Y_{11} \\right\} (\\mathrm{mS})$")
|
|
plt.legend()
|
|
fig = plt.figure()
|
|
plt.semilogx(
|
|
ac_data_built_in["frequency"],
|
|
ac_data_built_in["i(vsense).1"] * 1e3 / omega,
|
|
label="built-in",
|
|
linestyle=" ",
|
|
marker="x",
|
|
)
|
|
plt.semilogx(
|
|
ac_data_osdi["frequency"],
|
|
ac_data_osdi["i(vsense).1"] * 1e3 / omega,
|
|
label="OSDI",
|
|
)
|
|
plt.xlabel("$f(\\mathrm{H})$")
|
|
plt.ylabel("$\\Im\\left\{Y_{11}\\right\}/(\\omega) (\\mathrm{mF})$")
|
|
plt.legend()
|
|
|
|
# TR plot
|
|
fig = plt.figure()
|
|
plt.plot(
|
|
tr_data_built_in["time"] * 1e9,
|
|
tr_data_built_in["i(vsense)"] * 1e3,
|
|
label="built-in",
|
|
linestyle=" ",
|
|
marker="x",
|
|
)
|
|
plt.plot(
|
|
tr_data_osdi["time"] * 1e9,
|
|
tr_data_osdi["i(vsense)"] * 1e3,
|
|
label="OSDI",
|
|
)
|
|
plt.xlabel(r"$t(\mathrm{nS})$")
|
|
plt.ylabel(r"$I_{\mathrm{D}}(\mathrm{mA})$")
|
|
plt.legend()
|
|
|
|
plt.show()
|