/****************************************************************************
    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 __gateinfo_h
#define __gateinfo_h

#define bit(n) (1 << (n))

/*
   Special gate type codes.  All codes must be less than the value
   of GT_IGNORE.
*/
#define GT_RAM		1	/* RAM gate code */
#define GT_ROM		2	/* ROM gate code */
#define GT_CONCAT	3	/* Concatenation */
#define GT_IGNORE	100	/* Ignore gates of this type */

/*
   IO Codes
*/
#define GIO_IN		0	/* gate input */
#define GIO_OUT		1	/* gate output */
#define GIO_TRI		2	/* gate tristate output */
#define GIO_INOUT	3	/* gate bidirectional */
#define GIO_WIRE	4	/* special "wire" port type */


/*
   Pad flags
*/
#define PF_MULTI	0x1	/* Multiple pins on pad */
#define PF_CUT		0x2	/* Cut point for delay calculations */ 
#define PF_CLOCK	0x4	/* A clock port */
#define PF_CONST	0x8	/* A constant port */

/*
 * Describes chatacteristics of a pad.  A 'pad' is a set of
 * related ports.  For many ports on many gate types, there
 * is only one port on a pad.
 */
typedef struct spadinfo {
  char		*name;		/* Name of pad */
  int		io;		/* I/O type (GIO_*) */
  unsigned	flags;		/* Flags for pad (PF_*) */

  /* Automatically set values */
  int		idx;		/* Pad index */
} SPadInfo;

/*
 * Describes the ports for which a delay value concerns.  The 'from'
 * and 'to' members are the port numbers for which the delay value
 * corresponds to, but the input side is represented as a bitmask set
 * and the output side is an index.  If 'to' is -1, then this is a
 * delay added to an exit port (e.g., hold time of register).  If 'from'
 * is 0 (the empty set), then this is a delay added to a source port
 * (e.g., delay from clock to output on register).  If 'from' is 0 and
 * 'to' are -1, then this delay needs special handling.
 */
typedef struct {
  char		*ds_name;	/* Name of delay value */
  unsigned	ds_from;	/* Bitmask set of input pads */
  int		ds_to;		/* Output pad number */
} SDelaySpec;

typedef struct sgateinfo {
  int		gi_code;	/* Code number for a gate type */
  char		*gi_name;	/* Name of gate type */
  unsigned	gi_vmask;	/* Invert significant bit mask for gate type */
  int		gi_numPads;	/* Number of pads */
  SPadInfo	gi_pad[MAXPADS]; /* Pad info for gate type */ 

  SDelaySpec	gi_delayNames[MAXDELAYS];	/* Delay info for gate type */

  SGate		*(*gi_copyGate)(SGate*,const char*,SModule*);
  void		(*gi_processEvent)(SGate*,EvQueue*,SEvent*);
  int		(*gi_checkGate)(SGate*);
  void		(*gi_initGate)(EvQueue*,SGate*);
  void		(*gi_setProp)(SGate*,const char*,const void*);
  void		(*gi_command)(EvQueue *Q,SGate*,const char*);
  Memory	*(*gi_getMem)(SGate*);

  void		(*gi_propFrwdDelay)(SPort*,simTime);
  void		(*gi_propBackDelay)(SPort*,simTime);
  simTime	(*gi_delay)(SPort*,SPort*);
} SGateInfo;

void SGateInfo_register(SGateInfo*gi,const char*);	/* Register a new gate type */
unsigned SGateInfo_compMask(SGateInfo*,const char*); 	/* Get the port compliment mask for a type */
SGateInfo *SGateInfo_find(const char *name);		/* Find the named gate type */
int SGateInfo_portRank(SGateInfo*,const char*);	/* Return 'rank' of a port name */

int Generic_checkGate(SGate*);			/* Check a gate for errors */
SGate *Generic_copyGate(SGate*,const char*,SModule*);	/* Copy a gate to a module with a new name */
void Generic_setProp(SGate*,const char*,const void*);	/* Set a property of a gate */
void Generic_propFrwdDelay(SPort*,simTime); 	/* Propogate delay forward from a port */
void Generic_propBackDelay(SPort*,simTime);	/* Propogate delay backward from a port */
simTime	Generic_delay(SPort*,SPort*);		/* Delay between two ports on a gate */


void Nop_processEvent(SGate*,EvQueue*,SEvent*);	/* Dummy 'do nothing' event handler */
int Nop_checkGate(SGate*);			/* Dummy 'do nothing' error checker */
void Nop_initGate(EvQueue*,SGate*);		/* Dummy 'do nothing' initializer */

#endif
