Transfer Function Analysis#
Compute DC small-signal transfer function, input resistance, and output resistance.
import os
import sys
from pathlib import Path
# Set working directory to the PDK root if running from scripts/
if Path.cwd().name == "scripts":
os.chdir(Path.cwd().parent)
# Ensure ngspice shared library can be found (macOS homebrew)
if sys.platform == "darwin" and "/opt/homebrew/lib" not in os.environ.get(
"DYLD_LIBRARY_PATH", ""
):
os.environ["DYLD_LIBRARY_PATH"] = "/opt/homebrew/lib:" + os.environ.get(
"DYLD_LIBRARY_PATH", ""
)
import numpy as np
from nyancad.watch import watch_project_dir, file_schematic
from nyancad.netlist import inspice_netlist
from InSpice import Simulator
Parameters#
SCHEMATIC = "inverter" # stem of the .nyancir file
CORNER = "mos_tt"
# -- Transfer function parameters --
OUTPUT_VAR = "v(net0)" # output variable (e.g. "v(out)", "i(vload)")
INPUT_SOURCE = "VV2" # input source name
Load schematic and build netlist#
project = watch_project_dir(".")
schem_data = await file_schematic(project, SCHEMATIC)
spice = await inspice_netlist(SCHEMATIC, schem_data, corner=CORNER)
print(spice)
Duplicated lib ('ihp/models/ngspice/models/cornerMOSlv.lib', 'mos_tt')
.title schematic
.lib /Users/pepijndevos/code/IHP/ihp/models/ngspice/models/cornerMOSlv.lib mos_tt
VV1 W2 GND DC 1.8
VV2 W3 GND DC 0.9 AC 1 sin(0.9 0.5 1k)
XM1 W6 W3 GND GND sg13_lv_nmos l={0.13 * 1e-6} m=1 ng=1 w={0.15 * 1e-6}
XM2 W2 W3 W6 W2 sg13_lv_pmos l={0.13 * 1e-6} m=1 ng=1 w={0.15 * 1e-6}
CC1 W6 GND 1u
print("Netlist nodes:", list(spice.node_names))
print("Netlist elements:", list(spice.element_names))
Netlist nodes: ['0', 'W2', 'GND', 'W3', 'W6']
Netlist elements: ['VV1', 'VV2', 'XM1', 'XM2', 'CC1']
Run transfer function analysis#
simulator = Simulator.factory(simulator="ngspice-shared")
for osdi in [
"ihp/models/ngspice/osdi/psp103.osdi",
"ihp/models/ngspice/osdi/psp103_nqs.osdi",
"ihp/models/ngspice/osdi/r3_cmc.osdi",
"ihp/models/ngspice/osdi/mosvar.osdi",
]:
simulator._ngspice_shared.exec_command(f"osdi {osdi}")
simulation = simulator.simulation(spice)
analysis = simulation.transfer_function(
outvar=OUTPUT_VAR,
insrc=INPUT_SOURCE,
)
print("Transfer function analysis complete.")
Warning: can't find the initialization file spinit.
Newer Ngspice version that could be unsupported 46
Transfer function analysis complete.
Results#
print("Transfer function results:")
for key in analysis.nodes.keys():
val = np.array(analysis[key]).item()
print(f" {key} = {val:.6g}")
Transfer function results:
output_impedance_at_V(net0) = 1
vv2#Input_impedance = 4.94306e+11
Transfer_function = 0