//-----------------------------------------------------------------------------
// 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: circuit.hh
//
// Purpose: models a spice circuit netlist
//
// Remarks: 
//
// History: 03/22/97 - MAR - created.
// 	    05/07/02 - MRG - added output operators
//	    01/26/04 - STF - Updated for compatibility with g++ 3
//
// Copyright (c) 1997 Michael A. Riepe
// Copyright (c) 2002 Matthew R. Guthaus
// Copyright (c) 2004 Stephen T. Frezza
//
// RCS Version:
//     $Id: circuit.hh,v 1.2 2002/05/07 01:22:21 mguthaus Exp $
//-----------------------------------------------------------------------------

#ifndef __CIRCUIT__
#define __CIRCUIT__

// forward declarations
class subCircuit;
class circuit;

#ifdef HAVE_STL
   #include <stl>
#else
   #include <stl.h>
#endif
#include <vector>
#include <map>
#include <list>
using namespace std;
#include "argument.hh"
#include "device.hh"
#include "net.hh"
#include "port.hh"

//-----------------------------------------------------------------------------
// Class: subCircuit
//
// Purpose: models a spice netlist subCircuit, a netlist of components.
//
// Notes: Derived from class device so that it can be referenced by a port.
//-----------------------------------------------------------------------------

class subCircuit : public device {
public:

    //-------------------------------------------------------------------------
    // enumerated type for derived class identification
    //-------------------------------------------------------------------------
    enum {
        _SUBCIRCUIT_ = _ISOURCE_,
        _CIRCUIT_
    };

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

    subCircuit();
    subCircuit(char *name);
    virtual ~subCircuit();
		subCircuit(subCircuit& s);

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

    // remove device instances from subCircuit
    void remove_mosfet (mosfet *m);

    // add device instances to subCircuit
    bjt        *add_bjt (char *name, char *nc, char *nb, char *ne, char *ns);
    capacitor  *add_capacitor (char *name, char *node1, char *node2);
   coupling  *add_coupling (char *name, char *inductor1, char *inductor2);
    diode      *add_diode (char *name, char *nplus, char *nminus);
    inductor   *add_inductor (char *name, char *node1, char *node2);
    isource    *add_isource (char *name, char *plus_node, char *minus_node);
    jfet       *add_jfet (char *name, char *nd, char *ng, char *ns, char *nb);
    mosfet     *add_mosfet (char *name, char *nd, char *ng, char *ns, char *nb);
    resistor   *add_resistor (char *name, char *node1, char *node2);
    subcktinst *add_subcktinst (char *name, subCircuit &subDef, vector<char*> &nodes);
    vsource    *add_vsource (char *name, char *plus_node, char *minus_node);

    // copy devices instances from one subCircuit to another
    bjt        *copy_bjt (circuit *top, bjt *in_bjt, subcktinst *in_inst, char *prefix);
    capacitor  *copy_capacitor (circuit *top, capacitor *in_capacitor, subcktinst *in_inst, char *prefix);
    coupling  *copy_coupling (circuit *top, coupling *in_coupling, subcktinst *in_inst, char *prefix);
    diode      *copy_diode (circuit *top, diode *in_diode, subcktinst *in_inst, char *prefix);
    inductor   *copy_inductor (circuit *top, inductor *in_inductor, subcktinst *in_inst, char *prefix);
    isource    *copy_isource (circuit *top, isource *in_isource, subcktinst *in_inst, char *prefix);
    jfet       *copy_jfet (circuit *top, jfet *in_jfet, subcktinst *in_inst, char *prefix);
    mosfet     *copy_mosfet (circuit *top, mosfet *in_mosfet, subcktinst *in_inst, char *prefix);
    resistor   *copy_resistor (circuit *top, resistor *in_resistor, subcktinst *in_inst, char *prefix);
    subcktinst *copy_subcktinst (circuit *top, subcktinst *in_subcktinst, subcktinst *in_inst, char *prefix);
    vsource    *copy_vsource (circuit *top, vsource *in_vsource, subcktinst *in_inst, char *prefix);

    // propagate ports upwards
		void propagate_port(circuit *top, port& inp, port& newp, subcktinst *in_inst,char *prefix);

		friend ostream &operator<<(ostream& os, subCircuit& s);
    // access private members
    inline map<char*,device*,ltstr> &devices() { return _devices; }
    inline map<char*,port*,ltstr> &port_map() { return _port_map; }
    inline vector<port*> &port_vec() { return _port_vec; }
    inline map<char*, net*, ltstr> &nets() { return _nets; }

    void remove_net (net *n);
    inline net *add_net(char *net_name) { return add_net(net_name,false); }
    net *add_net(char *net_name, bool external);
    void remove_port (port *p);
    inline port *add_port(char *port_name) { return add_port(port_name, port::_UNSPECIFIED_); }
    port *add_port(char *port_name, port::dirEnum direction);

protected:

private:
    map<char*,device*,ltstr> _devices;              // a symbol table of devices
    map<char*,port*,ltstr> _port_map;                 // a symbol table of ports
    vector<port*> _port_vec;                       // an ordered vector of ports
    map<char*,net*,ltstr> _nets;                       // a symbol table of nets
};


//-----------------------------------------------------------------------------
// Class: circuit
//
// Purpose: Models a spice deck circuit netlist. It derives from subCircuit
//          because it can also be a netlist of components.  But the circuit
//          may also contain a symbol table of subCircuit definitions, and a
//          symbol table of device model name/type mappings.
//
// Notes: this definition imples that subcircuits cannot define their own
//        locally-scoped subcircuit definitions.  Subcircuit can contain
//        instances of other subcircuits, but all subckt definitions must
//        be global in scope.
//-----------------------------------------------------------------------------

class circuit : public subCircuit {
public:

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

    circuit();
    circuit(char *name);
    virtual ~circuit();

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

    // add device instances to subCircuit
    void add_bjt (char *name, ArgumentVec *args);
    void add_capacitor (char *name,ArgumentVec *args);
    void add_coupling (char *name,ArgumentVec *args);
    void add_diode (char *name, ArgumentVec *args);
    void add_inductor (char *name, ArgumentVec *args);
    void add_isource (char *name, ArgumentVec *args);
    void add_jfet (char *name, ArgumentVec *args);
    void add_mosfet (char *name, ArgumentVec *args);
    void add_resistor (char *name, ArgumentVec *args);
    void add_subcktinst (char *name, ArgumentVec *args);
    void add_vsource (char *name, ArgumentVec *args);
    void begin_subckt (ArgumentVec *args);
    void end_subckt (Argument *arg);
    void add_model (Argument *name_arg, Argument *type_arg, ArgumentVec *params);
    void process_comment (StringArgument *comment);

    void flatten(circuit *in_circ);

		friend ostream &operator<<(ostream& os, circuit& s);

    //access private members
    inline map<char*, char*, ltstr> &models() { return _models; }
    inline map<char*, subCircuit*, ltstr> &subckts() { return _subckts; }
    inline vector<char*> &app_commands() { return _app_commands; }
    inline char *gnd_node() { return _gnd_node; }
    inline char *vdd_node() { return _vdd_node; }
protected:

private:
    map<char*, char*, ltstr> _models;             // a symbol table of device models
    map<char*, subCircuit*, ltstr> _subckts; // a symbol table of subckt definitions
    vector<char*> _app_commands;          // a vector of commands to the application
    char *_gnd_node;                                        // node name of gnd node
    char *_vdd_node;                                        // node name of vdd node

    bool _doing_subckt;            // flag to indicate that we are defining a subckt
    subCircuit *_curr_subckt;    // pointer to current subckt being defined (if any)

    char *unpack_identifier(Argument *arg);
    char *unpack_S_identifier(Argument *arg);
    void flatten_subcktinst(circuit *in_circ, subcktinst *in_inst, char *prefix);
};


#endif // __CIRCUIT__

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