//-----------------------------------------------------------------------------
// COPYRIGHT  (c)  1997 
// THE REGENTS OF THE UNIVERSITY OF MICHIGAN
// ALL RIGHTS RESERVED
// 
// PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS 
// AND REDISTRIBUTE THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR 
// ANY PURPOSE, SO LONG AS NO FEE IS CHARGED, AND SO LONG AS 
// THE COPYRIGHT NOTICE ABOVE, THIS GRANT OF PERMISSION, AND 
// THE DISCLAIMER BELOW APPEAR IN ALL COPIES MADE; AND SO LONG 
// AS THE NAME OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY 
// ADVERTISING OR PUBLICITY PERTAINING TO THE USE OR 
// DISTRIBUTION OF THIS SOFTWARE WITHOUT SPECIFIC, WRITTEN 
// PRIOR AUTHORIZATION.
// 
// THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 
// FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS 
// FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE 
// UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR 
// IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
// REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 
// FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 
// CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT 
// HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH 
// DAMAGES.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// File: device.hh
//
// Purpose: Models a netlist device.  A set of derived classes for different
//          kinds of specialized devices.
//
// Remarks: 
//
// History: 03/22/97 - MAR - created.
//	    01/26/04 - STF - Modified to support g++-3
//
// Copyright (c) 1997 Michael A. Riepe
// Copyright (c) 2004 Stephen T. Frezza
//
// RCS Version:
//     $Id: device.hh,v 1.2 2002/05/07 01:22:21 mguthaus Exp $
//-----------------------------------------------------------------------------

#ifndef __DEVICE__
#define __DEVICE__

// forward declarations
class device;
class subcktinst;
class mosfet;
class jfet;
class bjt;
class diode;
class resistor;
class capacitor;
class coupling;
class inductor;
class vsource;
class isource;

#ifdef HAVE_STL
   #include <stl>
#else
   #include <stl.h>
#endif
#include <values.h>	
#include "functors.hh"
#include "argument.hh"
#include "port.hh"

//-----------------------------------------------------------------------------
// Class: device
//
// Purpose: Base class from which others are derived.
//-----------------------------------------------------------------------------

class device {
public:

    //-------------------------------------------------------------------------
    // enumerated type for derived class identification
    //-------------------------------------------------------------------------

    typedef int dev_type;
    enum {
        _DEVICE_ = 0,
        _SUBCKTINST_,
        _MOSFET_,
        _JFET_,
        _BJT_,
        _DIODE_,
        _RESISTOR_,
        _CAPACITOR_,
        _INDUCTOR_,
        _VSOURCE_,
        _ISOURCE_,
        _COUPLING_
    };

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    device();
    device(char *name);
    device(device &copy);
    virtual ~device();

    // virtual type information
    virtual dev_type which() { return _DEVICE_; }
    virtual int is_a(dev_type other) { return (other==_DEVICE_); }

    // dump contents
    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    inline void dump_params(ostream &os);

    // member access
    inline char * &name() {return _name;}
    inline device * &parent() { return _parent; }
    inline map<char*, double, ltstr> &Dparams() { return _Dparams; }
    inline map<char*, char*, ltstr> &Sparams() { return _Sparams; }
    
    // utilities
    inline double get_Dparam(char *pName) {
        if (_Dparams.count(pName))
            return _Dparams[pName];
        else
            return MINDOUBLE;  // Note: really should return a NaN here
    }
    inline double NULL_Dparam() {
        // defines the value which is returned for a NULL Dparam
        return MINDOUBLE;
    }

    inline char *get_Sparam(char *pName) {
        if (_Sparams.count(pName))
            return _Sparams[pName];
        else
            return NULL;
    }

    void set_parameter(char *pName, int pValue);
    void set_parameter(char *pName, double pValue);
    void set_parameter(char *pName, char *pValue);
    void add_parameter(char *pName, int pValue);
    void add_parameter(char *pName, double pValue);
    void add_parameter(char *pName, char *pValue);
    void add_parameter(ParameterArgument *arg);
    void copy_parameters(map<char*, double, ltstr> Dp);
    void copy_parameters(map<char*, char*, ltstr> Sp);

protected:
    port *add_port(char *name);

private:
    char *_name;                                      // the name of the device
    device *_parent;                    // parent device in hierarchical design
    map<char*, double, ltstr> _Dparams;  // a symbol table of double parameters
    map<char*, char*, ltstr> _Sparams;   // a symbol table of string parameters
};


//-----------------------------------------------------------------------------
// Class: subcktinst
//
// Purpose: A subcktinst can model an instance of a hierarchical component
//          with a list of ports.
//-----------------------------------------------------------------------------

class subcktinst : public device {
public:

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    subcktinst();
    subcktinst(char *name);
    subcktinst(char *name, vector<port*> &nPorts);
    subcktinst(subcktinst &copy);
    virtual ~subcktinst();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _SUBCKTINST_; }
    virtual int is_a(dev_type other) { return (other==_SUBCKTINST_); }

    inline char * &model_name() { return _model_name; }
    inline map<char*,port*,ltstr> &port_map() { return _port_map; }
    inline vector<port*> &port_vec() { return _port_vec; }
    
protected:

private:
    char *_model_name;            // name of the subckt this instantiates
    map<char*,port*,ltstr> _port_map;           // a map of the I/O ports
    vector<port*> _port_vec;                 // a vector of the I/O ports
};


//-----------------------------------------------------------------------------
// Class: mosfet
//
// Purpose: a model of a MOSFET (Metal Oxice Semiconductor Field Effect) device
//-----------------------------------------------------------------------------

class mosfet : public device {
public:

    //-------------------------------------------------------------------------
    // Enumberated types in local scope
    //-------------------------------------------------------------------------

    enum polarityEnum {_NFET_, _PFET_, _UNSPECIFIED_};

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    mosfet();
    mosfet(char *name);
    mosfet(mosfet &copy);
    virtual ~mosfet();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _MOSFET_; }
    virtual int is_a(dev_type other) { return (other==_MOSFET_); }

    inline port &drain() { return *_drain; }
    inline port &gate() { return *_gate; }
    inline port &source() { return *_source; }
    inline port &bulk() { return *_bulk; }

    inline char* &model() { return _model; }
    inline polarityEnum &polarity() { return _polarity; }

protected:

private:
    port *_drain;               // the drain port
    port *_gate;                // the gate port
    port *_source;              // the source port
    port *_bulk;                // the bulk port

    char *_model;              // a string containing the name of the spice model
    polarityEnum _polarity;    // the type of charge carrier (N or P type)
};


//-----------------------------------------------------------------------------
// Class: jfet
//
// Purpose: a model of a JFET (Junction Field Effect) device
//-----------------------------------------------------------------------------

class jfet : public device {
public:

    //-------------------------------------------------------------------------
    // Enumberated types in local scope
    //-------------------------------------------------------------------------

    enum polarityEnum {_NFET_, _PFET_, _UNSPECIFIED_};

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    jfet();
    jfet(char *name);
    jfet(jfet &copy);
    virtual ~jfet();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _JFET_; }
    virtual int is_a(dev_type other) { return (other==_JFET_); }

    inline port &drain() { return *_drain; }
    inline port &gate() { return *_gate; }
    inline port &source() { return *_source; }
    inline port &bulk() { return *_bulk; }

    inline char* &model() { return _model; }
    inline polarityEnum &polarity() { return _polarity; }

protected:

private:
    port *_drain;               // the drain port
    port *_gate;                // the gate port
    port *_source;              // the source port
    port *_bulk;                // the bulk port

    char *_model;              // a string containing the name of the spice model
    polarityEnum _polarity;    // the type of charge carrier (N or P type)
};


//-----------------------------------------------------------------------------
// Class: bjt
//
// Purpose: a model of a BJT Bipolar Junction Transistor) device
//-----------------------------------------------------------------------------

class bjt : public device {
public:

    //-------------------------------------------------------------------------
    // Enumberated types in local scope
    //-------------------------------------------------------------------------

    enum polarityEnum {_NPN_, _PNP_, _UNSPECIFIED_};

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    bjt();
    bjt(char *name);
    bjt(bjt &copy);
    virtual ~bjt();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _BJT_; }
    virtual int is_a(dev_type other) { return (other==_BJT_); }

    inline port &collector() { return *_collector; }
    inline port &base() { return *_base; }
    inline port &emitter() { return *_emitter; }
    inline port &substrate() { return *_substrate; }

    inline char* &model() { return _model; }
    inline polarityEnum &polarity() { return _polarity; }

protected:

private:
    port *_collector;           // the collector port
    port *_base;                // the base port
    port *_emitter;             // the emitter port
    port *_substrate;           // the substrate port

    char *_model;              // a string containing the name of the spice model
    polarityEnum _polarity;    // the type of charge carrier (N or P type)
};


//-----------------------------------------------------------------------------
// Class: diode
//
// Purpose: a model of a DIODE device
//-----------------------------------------------------------------------------

class diode : public device {
public:

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    diode();
    diode(char *name);
    diode(diode &copy);
    virtual ~diode();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _DIODE_; }
    virtual int is_a(dev_type other) { return (other==_DIODE_); }

    inline port &nplus() { return *_nplus; }
    inline port &nminus() { return *_nminus; }

    inline char* &model() { return _model; }

protected:

private:
    port *_nplus;               // the nplus port
    port *_nminus;              // the nminus port

    char *_model;              // a string containing the name of the spice model
};


//-----------------------------------------------------------------------------
// Class: resistor
//
// Purpose: a model of a RESISTOR device.
//-----------------------------------------------------------------------------

class resistor : public device {
public:

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    resistor();
    resistor(char *name);
    resistor(resistor &copy);
    virtual ~resistor();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _RESISTOR_; }
    virtual int is_a(dev_type other) { return (other==_RESISTOR_); }

    inline port &node1() { return *_node1; }
    inline port &node2() { return *_node2; }

    inline char* &model() { return _model; }

protected:

private:
    port *_node1;               // the node1 port
    port *_node2;               // the node2 port

    char *_model;              // a string containing the name of the spice model
};


//-----------------------------------------------------------------------------
// Class: capacitor
//
// Purpose: a model of a CAPACITOR device.
//-----------------------------------------------------------------------------

class capacitor : public device {
public:

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    capacitor();
    capacitor(char *name);
    capacitor(capacitor &copy);
    virtual ~capacitor();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _CAPACITOR_; }
    virtual int is_a(dev_type other) { return (other==_CAPACITOR_); }

    inline port &node1() { return *_node1; }
    inline port &node2() { return *_node2; }

    inline char* &model() { return _model; }

protected:

private:
    port *_node1;               // the node1 port
    port *_node2;               // the node2 port

    char *_model;              // a string containing the name of the spice model
};
//-----------------------------------------------------------------------------
// Class: coupling
//
// Purpose: a model of a COUPLING device.
//-----------------------------------------------------------------------------

class coupling : public device {
public:

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    coupling();
    coupling(char *name);
    coupling(coupling &copy);
    virtual ~coupling();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _COUPLING_; }
    virtual int is_a(dev_type other) { return (other==_COUPLING_); }

    inline port &inductor1() { return *_inductor1; }
    inline port &inductor2() { return *_inductor2; }

    

protected:

private:
    port *_inductor1;               // the inductor1 port
    port *_inductor2;               // the inductor2 port

   
};



//-----------------------------------------------------------------------------
// Class: inductor
//
// Purpose: a model of a linear INDUCTOR device.
//-----------------------------------------------------------------------------

class inductor : public device {
public:

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    inductor();
    inductor(char *name);
    inductor(inductor &copy);
    virtual ~inductor();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _INDUCTOR_; }
    virtual int is_a(dev_type other) { return (other==_INDUCTOR_); }

    inline port &node1() { return *_node1; }
    inline port &node2() { return *_node2; }

protected:

private:
    port *_node1;               // the node1 port
    port *_node2;               // the node2 port
};


//-----------------------------------------------------------------------------
// Class: vsource
//
// Purpose: a model of a voltage source device.
//-----------------------------------------------------------------------------

class vsource : public device {
public:

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    vsource();
    vsource(char *name);
    vsource(vsource &copy);
    virtual ~vsource();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _VSOURCE_; }
    virtual int is_a(dev_type other) { return (other==_VSOURCE_); }

    inline port &plus_node() { return *_plus_node; }
    inline port &minus_node() { return *_minus_node; }

protected:

private:
    port *_plus_node;           // the plus_node port
    port *_minus_node;          // the minus_node port
};


//-----------------------------------------------------------------------------
// Class: isource
//
// Purpose: a model of a current source device.
//-----------------------------------------------------------------------------

class isource : public device {
public:

    //-------------------------------------------------------------------------
    // Constructor/destructor.
    //-------------------------------------------------------------------------

    isource();
    isource(char *name);
    isource(isource &copy);
    virtual ~isource();

    virtual void dump(ostream &os);
    virtual void print(ostream &os);
    virtual dev_type which() { return _ISOURCE_; }
    virtual int is_a(dev_type other) { return (other==_ISOURCE_); }

    inline port &plus_node() { return *_plus_node; }
    inline port &minus_node() { return *_minus_node; }

protected:

private:
    port *_plus_node;           // the plus_node port
    port *_minus_node;          // the minus_node port
};


#endif // __DEVICE__

/*****************************************************************************/
