#!/usr/bin/env python3
#------------------------------------------------------------------------------
#
# run_spice_tests.py --
#
#    Run all ngspice tests, assuming an input file "devices.txt" containing,
#    with one entry per line:
#
#    <device_name>  <device_type>  <expected_value>
#
#    where <device_type> is one of:  mosfet, bipolar, capacitor, resistor, or diode.
#
#------------------------------------------------------------------------------

import re
import os
import sys
import subprocess
import multiprocessing

from plot_mosfet_iv import make_mosfet_iv_plot
from plot_bipolar_iv import make_bipolar_iv_plot
from plot_bipolar_beta import make_bipolar_beta_plot
from plot_diode_iv import make_diode_iv_plot

__dir__ = os.path.dirname(os.path.abspath(__file__))

def make_testdir(outdir):
    testdir = os.path.join(outdir, 'tests')
    if not os.path.exists(testdir):
        os.makedirs(testdir)
    return testdir


def getmake(outdir):
    testdir = make_testdir(outdir)

    testrunner = os.path.join(testdir, 'Makefile')
    # FIXME: Write out a Makefile
    with open(testrunner, 'w') as ofile:
        # FIXME: run ngspice

        # FIXME: run the check_XXXX.py script on the ngspice output

        # FIXME: run the plot_XXX.py script on the ngspice output


#------------------------------------------------------------------------------
# Read ".spice.in" file, replace DEVICENAME string with the device name,
# PDKVERSION with the version (v0.20.1), and CORNER with the simulation
# corner (tt), and write out as ".spice" file in "results" directory.
#------------------------------------------------------------------------------

def genspice(outdir, scriptname, devicename, version, corner):
    print('Generating simulation netlist for device ' + devicename)
    scripttype = scriptname.split('_', 1)[1]
    scriptpath = os.path.join(__dir__, scriptname+'.in')
    with open(scriptpath, 'r') as ifile:
        spicelines = ifile.read().splitlines()

    outlines = ['* '+devicename+' Spice Simulation Test']
    for line in spicelines:
        newline = line.replace('DEVICENAME', devicename)
        newline = newline.replace('PDKVERSION', version)
        newline = newline.replace('CORNER', corner)
        outlines.append(newline)

    testdir = make_testdir(outdir)

    testfile = os.path.join(testdir, devicename + '_' + scripttype)
    with open(testfile, 'w') as ofile:
        for line in outlines:
            print(line, file=ofile)

    return testfile

#------------------------------------------------------------------------------
# Run a spice simulation (or two) for the device specified in 'line' (obtained
# from the list of devices and expected values).
#------------------------------------------------------------------------------

def do_for_device(outdir, devicename, version, corner):
    if 'ind' in devicename:
        # Inductors not handled (yet)!
        pass
    elif 'cap_mim_' in devicename:
        devicetype = 'mimcap'
    elif 'cap_vpp_' in devicename:
        devicetype = 'capacitor'
    elif 'esd_rf_diode' in devicename:
        devicetype = 'diode_dev'
    elif 'diode_' in devicename:
        devicetype = 'diode'
    elif 'nfet_' in devicename:
        devicetype = 'nfet'
    elif 'pfet_' in devicename:
        devicetype = 'pfet'
    elif 'pnp_' in devicename:
        devicetype = 'pnp'
    elif 'npn_' in devicename:
        devicetype = 'npn'
    elif 'res_' in devicename:
        devicetype = 'resistor'
    else:
        print('Unknown device type for device name ' + devicename + '.  Cannot simulate.')
        return -1

    print('Diagnostic:  Determined device ' + devicename + ' to be type ' + devicetype)

    if devicetype in ('nfet', 'pfet'):
        genspice(outdir, devicetype + '_iv.spice', devicename, version, corner)
        genspice(outdir, devicetype + '_vth.spice', devicename, version, corner)
        genmake(
            outdir,
            {
                devicetype + '_iv.spice' : 'plot_mostfet_iv',
                devicetype + '_vth.spice': '',
            },
        )

    elif devicetype in ('npn', 'pnp'):
        genspice(outdir, devicetype + '_iv.spice', devicename, version, corner)
        genspice(outdir, devicetype + '_beta.spice', devicename, version, corner)
        genmake(
            outdir,
            {
                devicetype + '_iv.spice'  : 'plot_bipolar_iv',
                devicetype + '_beta.spice': 'plot_bipolar_beta',
            },
        )

    elif devicetype == 'mimcap':
        genspice(outdir, 'cap_mim_value.spice', devicename, version, corner)
        genmake(
            outdir,
            {
                'cap_mim_value.spice': None,
            },
        )

    elif devicetype == 'capacitor':
        genspice(outdir, 'cap_vpp_value.spice', devicename, version, corner)
        genmake(
            outdir,
            {
                'cap_vpp_value.spice': None,
            },
        )

    elif devicetype == 'resistor':
        genspice(outdir, 'res_value.spice', devicename, version, corner)
        genmake(
            outdir,
            {
                'res_value.spice': None,
            },
        )

    elif devicetype in ('diode', 'diode_dev'):
        genspice(outdir, devicetype + '_vth.spice', devicename, version, corner)
        genmake(
            outdir,
            {
                devicetype + '_iv.spice': 'plot_diode_iv',
            },
        )


#------------------------------------------------------------------------------
# Main script starts here (no arguments, at least for now)
#------------------------------------------------------------------------------
def main(d):
    # To do:  Loop through version and corner.  For now, fixed.
    version = 'v0.20.1'
    corner = 'tt'

    device = os.path.basename(d)

    dp = os.path.abspath(d)
    if not os.path.isdir(dp):
        print("Skipping:", dp)
        return 0
    do_for_device(dp,device,version,corner)
    return 0
    for c in sorted(os.listdir(dp)):
        if not os.path.isdir(c):
            print("Skipping:", c)
            continue

        cp = os.path.join(dp, c)


if __name__ == "__main__":
    for a in sys.argv[1:]:
        r = main(a)
        if r != 0:
            sys.exit(r)
    sys.exit(0)
