# -*- coding: utf-8 -*-

# MIT license
#
# Copyright (C) 2018 by XESS Corp.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

"""
An interface from SKiDL to PySpice.
"""

# Create a SKiDL library of SPICE elements. All PySpice-related info goes into
# a pyspice dictionary that is added as an attribute to the SKiDL Part object.


from skidl import Pin, Part, SchLib, SKIDL, TEMPLATE
from skidl.tools.spice import not_implemented, add_part_to_circuit

# Pin aliases.
_POS_DIPOLE_ALIASES = ['+', 'plus', 'anode', 'A']
_NEG_DIPOLE_ALIASES = ['-', 'minus', 'm', 'negative', 'neg', 'cathode', 'C', 'K']
_POS_IN_PORT_ALIASES = ['+i', 'i+', 'input_plus', 'plus_input']
_NEG_IN_PORT_ALIASES = ['-i', 'i-', 'input_minus', 'minus_input']
_POS_OUT_PORT_ALIASES = ['+o', 'o+', 'output_plus', 'plus_output']
_NEG_OUT_PORT_ALIASES = ['-o', 'o-', 'output_minus', 'minus_output']

pyspice_lib = SchLib(tool=SKIDL).add_parts(*[
    Part(
        name='A',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='XSPICE',
        description='XSPICE code module',
        ref_prefix='A',
        pyspice={
            'name': 'A',
            'kw': {'model':'model',},
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[]),
    Part(
        name='B',
        aliases=['behavsrc', 'BEHAVSRC', 'behavioralsource', 'BEHAVIORALSOURCE',],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='Behavioral source',
        description='Behavioral (arbitrary) source',
        ref_prefix='B',
        pyspice={
            'name': 'B',
            'kw':{
                'i':'i_expression', 'i_expression':'i_expression',
                'v':'v_expression', 'v_expression':'v_expression',
                'tc1': 'tc1', 'tc2':'tc2',
                'temp':'temperature', 'temperature':'temperature',
                'dtemp':'device_temperature', 'device_temperature':'device_temperature',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='C',
        aliases=['cap', 'CAP'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='cap capacitor',
        description='Capacitor',
        ref_prefix='C',
        pyspice={
            'name': 'C',
            'kw':{
                'value':'capacitance', 'capacitance':'capacitance',
                'model':'model', 'multiplier':'multiplier', 'm':'multiplier',
                'scale':'scale', 
                'temp':'temperature', 'temperature':'temperature',
                'dtemp':'device_temperature', 'device_temperature':'device_temperature',
                'ic':'initial_condition', 'initial_condition':'initial_condition',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='BEHAVCAP',
        aliases=['behavcap', 'behavioralcap', 'BEHAVIORALCAP',],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='behavioral capacitor',
        description='Behavioral capacitor',
        ref_prefix='C',
        pyspice={
            'name': 'BehavioralCapacitor',
            'kw':{
                'expression':'expression',
                'tc1': 'tc1', 'tc2':'tc2',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='SEMICAP',
        aliases=['semicap', 'semiconductorcap', 'SEMICONDUCTORCAP',],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='semiconductor capacitor',
        description='Semiconductor capacitor',
        ref_prefix='C',
        pyspice={
            'name': 'SemiconductorCapacitor',
            'kw':{
                'value':'capacitance', 'model':'model',
                'length':'length', 'l':'length',
                'width':'width', 'w':'width',
                'multiplier':'multiplier', 'm':'multiplier',
                'scale':'scale', 
                'temp':'temperature', 'temperature':'temperature',
                'dtemp':'device_temperature', 'device_temperature':'device_temperature',
                'ic':'initial_condition', 'initial_condition':'initial_condition',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='D',
        aliases=['diode', 'DIODE'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='diode rectifier',
        description='Diode',
        ref_prefix='D',
        pyspice={
            'name': 'D',
            'kw':{
                'model':'model', 'area':'area',
                'multiplier':'multiplier', 'm':'multiplier',
                'pj':'pj', 'off':'off', 
                'ic':'initial_condition', 'initial_condition':'initial_condition',
                'temp':'temperature', 'temperature':'temperature',
                'dtemp':'device_temperature', 'device_temperature':'device_temperature',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='E',
        aliases=['VCVS', 'vcvs'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='voltage-controlled voltage source',
        description='Voltage-controlled voltage source',
        ref_prefix='E',
        pyspice={
            'name': 'VCVS',
            'kw':{
                'gain':'voltage_gain', 'voltage_gain':'voltage_gain',
                'op':'output_plus', 'on':'output_minus', 'ip':'input_plus', 'in':'input_minus'
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='ip', func=Pin.PASSIVE, do_erc=True, alias=_POS_IN_PORT_ALIASES),
            Pin(num='2', name='in', func=Pin.PASSIVE, do_erc=True, alias=_NEG_IN_PORT_ALIASES),
            Pin(num='3', name='op', func=Pin.PASSIVE, do_erc=True, alias=_POS_OUT_PORT_ALIASES),
            Pin(num='4', name='on', func=Pin.PASSIVE, do_erc=True, alias=_NEG_OUT_PORT_ALIASES),
        ]),
    Part(
        name='NONLINV',
        aliases=['nonlinv', 'nonlinearvoltagesource', 'NONLINEARVOLTAGESOURCE'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='non-linear voltage source',
        description='Nonlinear voltage source',
        ref_prefix='E',
        pyspice={
            'name': 'NonLinearVoltageSource',
            'kw':{
                'expression':'expression', 'table':'table',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='F',
        aliases=['CCCS', 'cccs'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='current-controlled current source',
        description='Current-controlled current source',
        ref_prefix='F',
        pyspice={
            'name': 'CCCS',
            'kw':{
                'control':'source', 'source':'source',
                'gain':'current_gain', 'current_gain':'current_gain',
                'multiplier':'multiplier', 'm':'multiplier',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='G',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='voltage-controlled current source',
        description='Voltage-controlled current source',
        ref_prefix='G',
        pyspice={
            'name': 'VCCS',
            'kw':{
                'gain':'transconductance', 'current_gain':'transconductance',
                'multiplier':'multiplier', 'm':'multiplier',
                'op':'output_plus', 'on':'output_minus', 'ip':'input_plus', 'in':'input_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='ip', func=Pin.PASSIVE, do_erc=True, alias=_POS_IN_PORT_ALIASES),
            Pin(num='2', name='in', func=Pin.PASSIVE, do_erc=True, alias=_NEG_IN_PORT_ALIASES),
            Pin(num='3', name='op', func=Pin.PASSIVE, do_erc=True, alias=_POS_OUT_PORT_ALIASES),
            Pin(num='4', name='on', func=Pin.PASSIVE, do_erc=True, alias=_NEG_OUT_PORT_ALIASES),
        ]),
    Part(
        name='NONLINI',
        aliases=['nonlinvi', 'nonlinearcurrentsource', 'NONLINEARCURRENTSOURCE'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='non-linear current source',
        description='Nonlinear current source',
        ref_prefix='G',
        pyspice={
            'name': 'NonLinearCurrentSource',
            'kw':{
                'expression':'expression', 'table':'table',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='H',
        aliases=['CCVS', 'ccvs'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='current-controlled voltage source',
        description='Current-controlled voltage source',
        ref_prefix='H',
        pyspice={
            'name': 'H',
            'kw':{
                'control':'source', 'source':'source',
                'transresistance':'transresistance',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='I',
        aliases=['i', 'cs', 'CS'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='current source',
        description='Current source',
        ref_prefix='I',
        pyspice={
            'name': 'I',
            'kw':{
                'value':'dc_value', 'dc_value':'dc_value',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='J',
        aliases=['JFET', 'jfet'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='junction field-effect transistor JFET',
        description='Junction field-effect transistor',
        ref_prefix='J',
        pyspice={
            'name': 'J',
            'kw':{
                'model':'model', 'area':'area',
                'multiplier':'multiplier', 'm':'multiplier', 'off':'off', 
                'ic':'initial_condition', 'initial_condition':'initial_condition',
                'temp':'temperature', 'temperature':'temperature',
                'd':'drain', 'g':'gate', 's':'source',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='d', func=Pin.PASSIVE, do_erc=True, alias=['drain',]),
            Pin(num='2', name='g', func=Pin.PASSIVE, do_erc=True, alias=['gate',]),
            Pin(num='3', name='s', func=Pin.PASSIVE, do_erc=True, alias=['source',]),
        ]),
    Part(
        name='K',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='coupled mutual inductors',
        description='Coupled (mutual) inductors',
        ref_prefix='K',
        pyspice={
            'name': 'K',
            'kw': {
                'ind1':'ind1', 'ind2':'ind2', 'coupling':'coupling',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        coupled_parts=[],
        pins=[]),
    Part(
        name='L',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='inductor choke coil reactor magnetic',
        description='Inductor',
        ref_prefix='L',
        pyspice={
            'name': 'L',
            'kw':{
                'value':'inductance', 'inductance':'inductance',
                'model':'model', 'nt':'nt',
                'multiplier':'multiplier', 'm':'multiplier',
                'scale':'scale', 
                'temp':'temperature', 'temperature':'temperature',
                'dtemp':'device_temperature', 'device_temperature':'device_temperature',
                'ic':'initial_condition', 'initial_condition':'initial_condition',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='BEHAVIND',
        aliases=['behavind', 'behavioralind', 'BEHAVIORALIND',],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='behavioral inductor',
        description='Behavioral inductor',
        ref_prefix='C',
        pyspice={
            'name': 'BehavioralInductor',
            'kw':{
                'expression':'expression',
                'tc1': 'tc1', 'tc2':'tc2',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='M',
        aliases=['MOSFET', 'mosfet', 'FET', 'fet',],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='metal-oxide field-effect transistor MOSFET',
        description='Metal-oxide field-effect transistor',
        ref_prefix='M',
        pyspice={
            'name': 'M',
            'kw':{
                'model':'model',
                'multiplier':'multiplier', 'm':'multiplier',
                'l':'length', 'length':'length',
                'w':'width', 'width':'width',
                'drain_area':'drain_area',
                'source_area':'source_area',
                'drain_perimeter':'drain_perimeter',
                'source_perimeter':'source_perimeter',
                'drain_number_square':'drain_number_square',
                'source_number_square':'source_number_square',
                'off':'off', 
                'ic':'initial_condition', 'initial_condition':'initial_condition',
                'temp':'temperature', 'temperature':'temperature',
                'd':'drain', 'g':'gate', 's':'source', 'b':'bulk',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='d', func=Pin.PASSIVE, do_erc=True, alias=['drain',]),
            Pin(num='2', name='g', func=Pin.PASSIVE, do_erc=True, alias=['gate',]),
            Pin(num='3', name='s', func=Pin.PASSIVE, do_erc=True, alias=['source',]),
            Pin(num='4', name='b', func=Pin.PASSIVE, do_erc=True, alias=['bulk', 'substrate']),
        ]),
    Part( #####################################################################
        name='N',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='numerical device GSS',
        description='Numerical device for GSS',
        ref_prefix='N',
        pyspice={
            'name': 'N',
            'add': not_implemented,
        },
        num_units=1,
        do_erc=True,
        pins=[]),
    Part(
        name='O',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='lossy transmission line',
        description='Lossy transmission line',
        ref_prefix='O',
        pyspice={
            'name': 'O',
            'kw':{
                'model':'model',
                'op':'output_plus', 'on':'output_minus', 'ip':'input_plus', 'in':'input_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='ip', func=Pin.PASSIVE, do_erc=True, alias=_POS_IN_PORT_ALIASES),
            Pin(num='2', name='in', func=Pin.PASSIVE, do_erc=True, alias=_NEG_IN_PORT_ALIASES),
            Pin(num='3', name='op', func=Pin.PASSIVE, do_erc=True, alias=_POS_OUT_PORT_ALIASES),
            Pin(num='4', name='on', func=Pin.PASSIVE, do_erc=True, alias=_NEG_OUT_PORT_ALIASES),
        ]),
    Part(
        name='P',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='coupled multiconductor line',
        description='Coupled multiconductor line',
        ref_prefix='P',
        pyspice={
            'name': 'P',
            'kw':{
                'model':'model',
                'length':'length', 'l':'length',
                'op':'output_plus', 'on':'output_minus', 'ip':'input_plus', 'in':'input_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[]), #############################################################
    Part(
        name='Q',
        aliases=('BJT', 'bjt'),
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='bipolar transistor npn pnp',
        description='Bipolar Junction Transistor',
        ref_prefix='Q',
        pyspice={
            'name': 'Q',
            'kw':{
                'model':'model', 'area':'area', 'areab':'areab', 'areac':'areac',
                'multiplier':'multiplier', 'm':'multiplier',
                'off':'off', 
                'ic':'initial_condition', 'initial_condition':'initial_condition',
                'temp':'temperature', 'temperature':'temperature',
                'dtemp':'device_temperature', 'device_temperature':'device_temperature',
                'c':'collector', 'b':'base', 'e':'emitter', 's':'substrate',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='c', func=Pin.PASSIVE, do_erc=True, alias=['collector',]),
            Pin(num='2', name='b', func=Pin.PASSIVE, do_erc=True, alias=['base',]),
            Pin(num='3', name='e', func=Pin.PASSIVE, do_erc=True, alias=['emitter',]),
            Pin(num='4', name='s', func=Pin.PASSIVE, do_erc=True, alias=['substrate', 'bulk']),
        ]),
    Part(
        name='R',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='res resistor',
        description='Resistor',
        ref_prefix='R',
        pyspice={
            'name': 'R',
            'kw':{
                'value':'resistance', 'resistance':'resistance',
                'ac':'ac', 'multiplier':'multiplier', 'm':'multiplier',
                'scale':'scale', 
                'temp':'temperature', 'temperature':'temperature',
                'dtemp':'device_temperature', 'device_temperature':'device_temperature',
                'noisy':'noisy',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='BEHAVRES',
        aliases=['behavres', 'behavioralresistor', 'BEHAVIORALRESISTOR',],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='behavioral resistor',
        description='Behavioral resistor',
        ref_prefix='R',
        pyspice={
            'name': 'BehavioralResistor',
            'kw':{
                'expression':'expression',
                'tc1': 'tc1', 'tc2':'tc2',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='SEMIRES',
        aliases=['semires', 'semiconductorresistor', 'SEMICONDUCTORRESISTOR',],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='semiconductor resistor',
        description='Semiconductor resistor',
        ref_prefix='R',
        pyspice={
            'name': 'SemiconductorResistor',
            'kw':{
                'value':'capacitance', 'capacitance':'capacitance',
                'model':'model',
                'ac':'ac',
                'length':'length', 'l':'length',
                'width':'width', 'w':'width',
                'multiplier':'multiplier', 'm':'multiplier',
                'scale':'scale', 
                'temp':'temperature', 'temperature':'temperature',
                'dtemp':'device_temperature', 'device_temperature':'device_temperature',
                'noisy':'noisy',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='S',
        aliases=['VCS', 'vcs'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='voltage-controlled switch',
        description='Voltage-controlled switch',
        ref_prefix='S',
        pyspice={
            'name': 'S',
            'kw':{
                'model':'model',
                'initial_state':'initial_state',
                'op':'output_plus', 'on':'output_minus', 'ip':'input_plus', 'in':'input_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='ip', func=Pin.PASSIVE, do_erc=True, alias=_POS_IN_PORT_ALIASES),
            Pin(num='2', name='in', func=Pin.PASSIVE, do_erc=True, alias=_NEG_IN_PORT_ALIASES),
            Pin(num='3', name='op', func=Pin.PASSIVE, do_erc=True, alias=_POS_OUT_PORT_ALIASES),
            Pin(num='4', name='on', func=Pin.PASSIVE, do_erc=True, alias=_NEG_OUT_PORT_ALIASES),
        ]),
    Part(
        name='T',
        aliases=['transmissionline', 'TRANSMISSIONLINE'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='transmission line',
        description='Transmission line',
        ref_prefix='T',
        pyspice={
            'name': 'TransmissionLine',
            'add': add_part_to_circuit,
            'kw':{
                'impedance':'impedance', 'Z0':'impedance',
                'time_delay':'time_delay', 'TD':'time_delay',
                'frequency':'frequency', 'F':'frequency',
                'normalized_length':'normalized_length', 'NL':'normalized_length',
                'op':'output_plus', 'on':'output_minus', 'ip':'input_plus', 'in':'input_minus',
            },
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='ip', func=Pin.PASSIVE, do_erc=True, alias=_POS_IN_PORT_ALIASES),
            Pin(num='2', name='in', func=Pin.PASSIVE, do_erc=True, alias=_NEG_IN_PORT_ALIASES),
            Pin(num='3', name='op', func=Pin.PASSIVE, do_erc=True, alias=_POS_OUT_PORT_ALIASES),
            Pin(num='4', name='on', func=Pin.PASSIVE, do_erc=True, alias=_NEG_OUT_PORT_ALIASES),
        ]),
    Part(
        name='U',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='uniformly-distributed RC line',
        description='Uniformly-distributed RC line',
        ref_prefix='U',
        pyspice={
            'name': 'U',
            'kw': {
                'model':'model',
                'length':'length', 'l':'length',
                'number_of_lumps':'number_of_lumps', 'm':'number_of_lumps',
                'o':'output', 'i':'input', 'cn':'capacitance_node',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='o', func=Pin.PASSIVE, do_erc=True, alias=['output']),
            Pin(num='2', name='i', func=Pin.PASSIVE, do_erc=True, alias=['input',]),
            Pin(num='3', name='cn', func=Pin.PASSIVE, do_erc=True, alias=['cap_node', 'capacitance_node']),
        ]),
    Part(
        name='V',
        aliases=['v', 'VS', 'vs', 'AMMETER', 'ammeter',],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='voltage source',
        description='Voltage source',
        ref_prefix='V',
        pyspice={
            'name': 'V',
            'kw':{
                'value':'dc_value', 'dc_value':'dc_value',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='W',
        aliases=['CCS', 'ccs'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='current-controlled switch',
        description='Current-controlled switch',
        ref_prefix='W',
        pyspice={
            'name': 'W',
            'kw':{
                'control':'source', 'source':'source', 'model':'model',
                'initial_state':'initial_state',
                'p':'plus', 'n':'minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    # Part( #####################################################################
        # name='X',
        # dest=TEMPLATE,
        # tool=SKIDL,
        # keywords='subcircuit',
        # description='Subcircuit',
        # ref_prefix='Y',
        # pyspice={
            # 'name': 'SubCircuitElement',
            # 'add': _add_subcircuit_to_circuit,
        # },
        # num_units=1,
        # do_erc=True,
        # pins=[]),
    Part(
        name='Y',
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='single lossy transmission line',
        description='Single lossy transmission line',
        ref_prefix='Y',
        pyspice={
            'name': 'Y',
            'kw':{
                'model':'model',
                'length':'length', 'l':'length',
                'op':'output_plus', 'on':'output_minus', 'ip':'input_plus', 'in':'input_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='ip', func=Pin.PASSIVE, do_erc=True, alias=_POS_IN_PORT_ALIASES),
            Pin(num='2', name='in', func=Pin.PASSIVE, do_erc=True, alias=_NEG_IN_PORT_ALIASES),
            Pin(num='3', name='op', func=Pin.PASSIVE, do_erc=True, alias=_POS_OUT_PORT_ALIASES),
            Pin(num='4', name='on', func=Pin.PASSIVE, do_erc=True, alias=_NEG_OUT_PORT_ALIASES),
        ]),
    Part(
        name='Z',
        aliases=['MESFET', 'mesfet'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='metal-semiconductor field-effect transistor MOSFET',
        description='Metal-semiconductor field-effect transistor',
        ref_prefix='Z',
        pyspice={
            'name': 'Z',
            'kw':{
                'model':'model',
                'area':'area',
                'multiplier':'multiplier', 'm':'multiplier',
                'off':'off', 
                'ic':'initial_condition', 'initial_condition':'initial_condition',
                'd':'drain', 'g':'gate', 's':'source',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='d', func=Pin.PASSIVE, do_erc=True, alias=['drain',]),
            Pin(num='2', name='g', func=Pin.PASSIVE, do_erc=True, alias=['gate',]),
            Pin(num='3', name='s', func=Pin.PASSIVE, do_erc=True, alias=['source',]),
        ]),
    Part(
        name='SINEV',
        aliases=['sinev', 'sinusoidalvoltage', 'SINUSOIDALVOLTAGE'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='simusoidal voltage source',
        description='Sinusoidal voltage source',
        ref_prefix='V',
        pyspice={
            'name': 'SinusoidalVoltageSource',
            'kw':{
                'dc_offset':'dc_offset', 'offset':'offset',
                'amplitude':'amplitude', 'frequency':'frequency',
                'delay':'delay', 'damping_factor':'damping_factor',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='SINEI',
        aliases=['sinei', 'sinusoidalcurrent', 'SINUSOIDALCURRENT'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='simusoidal current source',
        description='Sinusoidal current source',
        ref_prefix='I',
        pyspice={
            'name': 'SinusoidalCurrentSource',
            'kw':{
                'dc_offset':'dc_offset', 'offset':'offset',
                'amplitude':'amplitude', 'frequency':'frequency',
                'delay':'delay', 'damping_factor':'damping_factor',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='PULSEV',
        aliases=['pulsev', 'pulsevoltage', 'PULSEVOLTAGE'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='pulsed voltage source',
        description='Pulsed voltage source',
        ref_prefix='V',
        pyspice={
            'name': 'PulseVoltageSource',
            'kw':{
                'initial_value':'initial_value', 'pulsed_value':'pulsed_value',
                'delay_time':'delay_time', 'rise_time':'rise_time',
                'fall_time':'fall_time', 'pulse_width':'pulse_width',
                'period':'period',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='PULSEI',
        aliases=['pulsei', 'pulsecurrent', 'PULSECURRENT'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='pulsed current source',
        description='Pulsed current source',
        ref_prefix='I',
        pyspice={
            'name': 'PulseCurrentSource',
            'kw':{
                'initial_value':'initial_value', 'pulsed_value':'pulsed_value',
                'delay_time':'delay_time', 'rise_time':'rise_time',
                'fall_time':'fall_time', 'pulse_width':'pulse_width',
                'period':'period',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='EXPV',
        aliases=['expv', 'exponentialvoltage', 'EXPONENTIALVOLTAGE'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='exponential voltage source',
        description='Exponential voltage source',
        ref_prefix='V',
        pyspice={
            'name': 'ExponentialVoltageSource',
            'kw':{
                'initial_value':'initial_value', 'pulsed_value':'pulsed_value',
                'rise_delay_time':'rise_delay_time', 'rise_time_constant':'rise_time_constant',
                'fall_delay_time':'fall_delay_time', 'fall_time_constant':'fall_time_constant',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='EXPI',
        aliases=['expi', 'exponentialcurrent', 'EXPONENTIALCURRENT'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='exponential current source',
        description='Exponential current source',
        ref_prefix='I',
        pyspice={
            'name': 'ExponentialCurrentSource',
            'kw':{
                'initial_value':'initial_value', 'pulsed_value':'pulsed_value',
                'rise_delay_time':'rise_delay_time', 'rise_time_constant':'rise_time_constant',
                'fall_delay_time':'fall_delay_time', 'fall_time_constant':'fall_time_constant',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='PWLV',
        aliases=['pwlv', 'piecewiselinearvoltage', 'PIECEWISELINEARVOLTAGE'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='piecewise linear voltage source',
        description='Piecewise linear voltage source',
        ref_prefix='V',
        pyspice={
            'name': 'PieceWiseLinearVoltageSource',
            'kw':{
                'values':'values', 'repeate_time':'repeate_time',
                'delay_time':'delay_time',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='PWLI',
        aliases=['pwli', 'piecewiselinearcurrent', 'PIECEWISELINEARCURRENT'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='piecewise linear current source',
        description='Piecewise linear current source',
        ref_prefix='I',
        pyspice={
            'name': 'PieceWiseLinearCurrentSource',
            'kw':{
                'values':'values', 'repeate_time':'repeate_time',
                'delay_time':'delay_time',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='FMV',
        aliases=['fmv', 'SFFMV', 'sffmv', 'SINGLEFREQUENCYFMVOLTAGE', 'singlefrequencyfmvoltage'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='single frequency FM modulated voltage source',
        description='Single-frequency FM-modulated voltage source',
        ref_prefix='V',
        pyspice={
            'name': 'SingleFrequencyFMVoltageSource',
            'kw':{
                'offset':'offset', 'amplitude':'amplitude',
                'carrier_frequency':'carrier_frequency',
                'modulation_index':'modulation_index',
                'signal_frequency':'signal_frequency',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='FMI',
        aliases=['fmi', 'SFFMI', 'sffmi', 'SINGLEFREQUENCYFMCURRENT', 'singlefrequencyfmcurrent'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='single frequency FM modulated current source',
        description='Single-frequency FM-modulated current source',
        ref_prefix='I',
        pyspice={
            'name': 'SingleFrequencyFMCurrentSource',
            'kw':{
                'offset':'offset', 'amplitude':'amplitude',
                'carrier_frequency':'carrier_frequency',
                'modulation_index':'modulation_index',
                'signal_frequency':'signal_frequency',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='AMV',
        aliases=['amv', 'AMPLITUDEMODULATEDVOLTAGE', 'amplitudemodulatedvoltage'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='amplitude modulated voltage source',
        description='Amplitude-modulated voltage source',
        ref_prefix='V',
        pyspice={
            'name': 'AmplitudeModulatedVoltageSource',
            'kw':{
                'offset':'offset', 'amplitude':'amplitude',
                'carrier_frequency':'carrier_frequency',
                'modulating_frequency':'modulating_frequency',
                'signal_delay':'signal_delay',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='AMI',
        aliases=['ami', 'AMPLITUDEMODULATEDCURRENT', 'amplitudemodulatedcurrent'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='amplitude modulated current source',
        description='Amplitude-modulated current source',
        ref_prefix='I',
        pyspice={
            'name': 'AmplitudeModulatedCurrentSource',
            'kw':{
                'offset':'offset', 'amplitude':'amplitude',
                'carrier_frequency':'carrier_frequency',
                'modulating_frequency':'modulating_frequency',
                'signal_delay':'signal_delay',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='RNDV',
        aliases=['rndv', 'RANDOMVOLTAGE', 'randomvoltage'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='random voltage source',
        description='Random voltage source',
        ref_prefix='V',
        pyspice={
            'name': 'RandomVoltageSource',
            'kw':{
                'random_type':'random_type', 'duration':'duration',
                'time_delay':'time_delay',
                'parameter1':'parameter1',
                'parameter2':'parameter2',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
    Part(
        name='RNDI',
        aliases=['rndi', 'RANDOMCURRENT', 'randomcurrent'],
        dest=TEMPLATE,
        tool=SKIDL,
        keywords='random current source',
        description='Random current source',
        ref_prefix='I',
        pyspice={
            'name': 'RandomCurrentSource',
            'kw':{
                'random_type':'random_type', 'duration':'duration',
                'time_delay':'time_delay',
                'parameter1':'parameter1',
                'parameter2':'parameter2',
                'p':'node_plus', 'n':'node_minus',
            },
            'add': add_part_to_circuit,
        },
        num_units=1,
        do_erc=True,
        pins=[
            Pin(num='1', name='p', func=Pin.PASSIVE, do_erc=True, alias=_POS_DIPOLE_ALIASES),
            Pin(num='2', name='n', func=Pin.PASSIVE, do_erc=True, alias=_NEG_DIPOLE_ALIASES),
        ]),
])
