/****************************************************************************
    Copyright (C) 1987-2005 by Jeffery P. Hansen

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************/
#ifndef __module_h
#define __module_h

#define NF_ERRREP	0x2	/* We have reported errors on this net */
#define NF_DPATH	0x4	/* We have completed delay reporting (for forward paths) */
#define NF_LPCHECK	0x8	/* Combinational loop checking flag */

#define GF_ERRREP	0x1	/* We have reported errors on this gate */
#define GF_CPCUT	0x2	/* Gate is a critical path cutpoint */

struct sport {
  char		*p_name;	/* Name of port */
  unsigned	p_comp;		/* Compliment mask of port */
  SNet		*p_net;		/* Net connected to port */

  SGate		*p_gate;	/* Gate port is connected to */
  short		p_gpos;		/* Position on connected gate */
  short		p_isDup;	/* This is a duplicate read port on net */ 
  SPadInfo	*p_type;	/* Type info for port */
  SState	p_state;	/* State driven on port */
  SState	p_qstate;	/* Last state queued for port */
  simTime	p_nedge;	/* Time of next transition */
  simTime	p_ledge;	/* Time of last transition */
  double	p_dynamicPower;	/* Dynamic power estimate for changes on port */

  simTime	p_frwdDelay;	/* Longest delay from an input */
  simTime	p_backDelay;	/* Longest delay to an output */
};

struct sportlist {
  int		num;		/* Number of ports in list */
  SPort		**port;		/* Array of ports */
};

struct snet {
  char		*n_name;	/* Name of net */
  SNet		*n_source;	/* Net from which this net was created */
  int		n_nbits;	/* Bit-width of net */
  SPortList	n_ports;	/* Ports connected to net */
  unsigned	n_flags;	/* Net flags */
  SNet		*n_merge;	/* Net this net has been merged into */
  NHash		*n_watchNames;	/* Names under which net is watched */
  NHash		*n_breaks;	/* Breakpoints on this net */

  SState	n_state;	/* State of net */
  SState	n_oldState;	/* Previous state of net */

  simTime	n_frwdDelay;	/* Longest delay from an input */
  simTime	n_backDelay;	/* Longest delay to an output */
};

struct sgate {
  SGateInfo	*g_type;	/* Type information on gate */
  SGate		*g_source;	/* Gate from which this gate was copied */
  unsigned	g_flags;	/* Gate flags */
  char		*g_typeName;	/* Name of gate type */
  char		*g_name;	/* Name of gate */
  SPortList	g_ports;	/* Ports on this gate */
  void		*g_data;	/* Gate type-specific data (e.g., state for memories) */
  int		*g_delayParms;	/* Delay parameters for this gate */
  double	g_area;		/* Area estimate of gate */
  double	g_staticPower;	/* Static power estimate of gate */
  char		*g_tech;	/* Technology for gate */
};

struct smodule {
  char		*m_name; 
  SPortList	m_ports;	/* Ports on this gate */
  SHash		m_nets;		/* Nets in module */
  SHash		m_gates;	/* Gates in module */
};

SModule *new_SModule(const char*);		/* Creates a new module */
void SModule_addPort(SModule*,SNet*);		/* Make a net a port of a module */
SNet *SModule_findAddNet(SModule*,const char*);	/* Finds (or creates) a net by name in a module */
SNet *SModule_findNet(SModule*,const char*);	/* Finds a net by name in a module */
SGate *SModule_findGate(SModule*,const char*);	/* Finds a gate by name in a module */
void SModule_addGate(SModule*,SGate*);		/* Adds a gate to a module */
void SModule_print(SModule*,FILE*);		/* Prints a module (for debugging) */
void SModule_expand(SModule*);			/* Expands modules in the top-level module */
void SModule_finalize(SModule*);		/* Does a final initialization before simulation */
void SModule_check(SModule *M);			/* Check module for errors */
void SModule_init(SModule *M,EvQueue*);		/* Initializes gates in a module */

SGate *new_SGate(const char *gtype,const char *name);	/* Creates a new gate */
void SGate_addPort(SGate*,const char*,SNet*,int);	/* Adds a port to a gate */
void SGate_print(SGate*,FILE*);			/* Prints a gate (for debugging) */
void SGate_finalize(SGate*);			/* Finalizes a before simulation */
void SGate_errMark(SGate*);			/* Marks a gate as erroneous */
int SGate_isErrMarked(SGate*);			/* Checks for the error mark on a gate */
SState *SGate_allocPortState(SGate *g,int p);	/* Allocates port state for a gate */
void SGate_sortPins(SGate *g);			/* Puts gate ports in standard order */

SPort *new_SPort(const char *name,SNet *n,int inv);	/* Creates a new port */
void SPort_process(SPort*,EvQueue*,SEvent*);	/* Process an event on a port */
int SPort_effectiveTypeAux(SPort*);		/* Get the effective type of a port (on concat) */
#define SPort_effectiveType(P)			((P)->p_type->io <= GIO_OUT   ? (P)->p_type->io : SPort_effectiveTypeAux(P))
#define SPort_getPadIdx(p)	(p)->p_type->idx



void SPortList_init(SPortList*);		/* Initialize a port list */
void SPortList_add(SPortList*,SPort*);		/* Add a port to a port list */

SNet *new_SNet(const char *name,int nbits);		/* Create a new net */
void SNet_setNBits(SNet *n,int nbits);		/* Set bit width of net */
void SNet_attachPort(SNet*,SPort*);		/* Attach a port to a net */
void SNet_process(SNet*,EvQueue*,SEvent*);	/* Process an event on a net */
SNet *SNet_canonical(SNet*);			/* Return a net's canonical net */
void SNet_errMark(SNet *n);			/* Mark a net as an error */
int SNet_isErrMarked(SNet *n);			/* Test for an error on a net */

void SNet_propBackDelay(SNet*,simTime t); 	/* Propogate delay t back from net */  
void SNet_propFrwdDelay(SNet*,simTime t); 	/* Propogate delay t forward from net */  

int Concat_effectivePortType(SPort *P);		/* Get the effective port type */

#endif
