You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

162 lines
4.6 KiB

""" 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()