/****************************************************************************
    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.
****************************************************************************/
/*
    Declarations for circuit representation structures.
*/
#ifndef __elements_h
#define __elements_h

typedef struct editstate EditState;
typedef struct celemnt GCElement;
typedef struct gateinfo GGateInfo;
typedef struct simmodule GSimModule;
typedef struct modlayout GModLayout;

/*
   Data structure for specifying a functional block definition.
*/
typedef struct module_def_str {
  char *Name;			/* Enviornment name */
  unsigned prot : 1;		/* Write protect */
  unsigned used : 1;		/* Mark to see if used in circuit */
  unsigned nokill : 1;		/* Block can not be killed */
  unsigned is_top : 1;		/* Is this the top-level block? */
  unsigned is_lib : 1;		/* This is a library module */
  struct wirelist *wires;	/* Wires in module */
  SHash *gates;			/* Table of gates in module */
  SHash *nets;			/* Table of nets in module */
  GCElement *blockdescript;	/* I/O Description */
} GModuleDef;

typedef struct wirelist {
  struct wire *car;
  struct wirelist *cdr;
} GWireList;

typedef struct {
  int driver;			/* Which joint is driver */
  int gidx;			/* Index of joint (for reading circuits) */
} GGateJoint;

typedef struct {
  char *memfile;		/* File Containing memory definition */
} GGateMem;

typedef struct {
  int gwidth,gheight;		/* Block dimensions */
  char *BlockFunction;		/* Function definition of block */
} GGateBlock;

typedef struct {
  short omega,phi,duty;
} GGateClock;

typedef struct {
  unsigned perm_dipval;		/* Permanent dipval */
  unsigned dipval;		/* Current value */
  unsigned in_edit;		/* Currently editing value */
} GGateDip;

typedef struct {
  unsigned ltype;		/* Type of LED */
  unsigned value;		/* Current led value */
  unsigned valid;		/* Valid bits in value */
} GGateLed;

typedef struct {
  int spliceside;		/* Specifies which side of the wire the splice it on */
  int msb,lsb;			/* Range of bits selected by splice */
  int gidx;			/* Index of splice (for reading circuits) */
} GGateTap;

typedef struct {
  int direction;		/* Specifies direction wires are layed out */
} GGateConcat;

typedef struct {
  int extbar;			/* Use extender bar for multi-input basic gates */
} GGateBasic;

typedef struct comment_line {
  char	*text;			/* Text on the line */
  struct comment_line *next;	/* Next line */
} ComLine;

typedef struct {
  int	width,height;
  int		doLink;		/* This is an active hyperlink */
  char		*link;		/* Hyperlink file. */
  ComLine	*first;
  ComLine	*last;
} GGateComment;

typedef struct {
  int	width,height;
  char	*text;
} GGateFrame;

struct celemnt {
  GGateInfo *typeinfo;		/* Type information of gate */
  char *ename;			/* Element Name */
  int enumb;			/* Element number */
  int xpos,ypos,orient,size;	/* Position of element */
  char *tech;			/* Technology of gate */
  int *delays;			/* Delay values for the gate */

  unsigned selected:1;		/* Gate selected */
  unsigned top:1;		/* Top edge selected */
  unsigned bottom:1;		/* Bottom edge selected */
  unsigned right:1;		/* Right edge selected */
  unsigned left:1;		/* Left edge selected */
  unsigned mark:1;		/* Generic mark for gates */
  unsigned show_name:1;		/* Names should be displayed */
  unsigned anchored:1;		/* Gate position is fixed */
  unsigned cpath_cut:1;		/* Gate is a critical path cut-point */
  unsigned cust_delay:1;	/* Use custom delay values */

  struct wire *wires[MAXWIRES];
  union {
    GGateClock	clock;
    GGateDip	sw;
    GGateLed	led;
    GGateTap	tap;
    GGateJoint	joint;
    GGateMem	mem;
    GGateBlock	block;
    GGateConcat	cat;
    GGateBasic	basic;
    GGateFrame	frame;
    GGateComment comment;
  } u;
};

/*
   A Net is a collection of wires and wire segments all connected by
   joints and outsplices.
*/
typedef struct net GNet;
struct net {
  char		*signame;	/* Signal name of this net */
  int		nbits;		/* Bit width of this net */
  short 	dtype;		/* Unused */
  int		refs;		/* Reference count */
  GModuleDef	*mod;		/* Module this net is in */
  GCElement	*ionet;		/* I/O gate if this is a port */
  unsigned	mark : 1;	/* Mark for nets */
  unsigned	show_name : 1;	/* Is net name visible? */
  int		decoration;	/* The wire number of the segment end to decorate */
  short		wnum;		/* Counter for counting wires */
  short		gnum;		/* Counter for counting joints, etc. */
  struct wire	*driver;	/* Driver wire of net */
  GNet		*next;		/* Next net in freelist */
};

/*
   A "wire" is really an end point of a wire segment.  It might have been
   more appropriate to call it a port. 
*/
typedef struct wire {
  GNet	*net;			/* Net this wire is a part of */
  char *name;			/* Port name (if connected to a block) */
  int nidx;			/* Index within net */
  unsigned invert : 1;		/* Inverter at this end? */
  unsigned xanchor : 1;		/* X coordinate is anchored */
  unsigned yanchor : 1;		/* Y coordinate is anchored */
  unsigned cpath : 1;		/* Is this seg. on displayed path? */
  short orient;			/* Orientation: UP, RIGHT, DOWN, LEFT */
  struct {
    short num,den;		/* Offset of wire position (as a fraction) */
  } offset;
  char wtype;			/* DRIVER/DRIVEE tag */
  short PadNum;			/* Pad number (computed before simulation) */
  short WireDir;		/* Direction  (computed before simulation) */
  struct celemnt *gate;		/* Gate connected to this wire end */
  struct wirenode *nodes;	/* Nodes on this wire */
  struct wire *driver;		/* Driving end of wire */
  struct wire *next;		/* Next wire in global list */
} GWire;

typedef struct wirenode {
  int x,y;			/* Node position */
  char stype;			/* What kind of node selection */
  char mark;			/* Has this node been touched */
  struct wirenode *out;		/* Output nodes */
  struct wirenode *in;		/* Input nodes */
  struct wire *end;		/* End of wire */
} GWireNode;

/*
   Used for gateinfo on wires.
*/
typedef struct padinfo {
  char *Name;			/* Pin name for wires on this pad */
  int Dir;			/* Direction */
  int Size;			/* Default bit-size */
  int Num;			/* Initial number of pins */
  struct locate *Loc;		/* Location info for pins */
  unsigned CanAdd : 1;		/* Can add to pin list */
} GPadInfo;

/*
  Used to specify the position of a gate name label.
 */
typedef struct {
  int x,y;			/* Position of label */
  int just;			/* Justification mode for text */
} GLabelPos;

typedef struct gKeyMenuEnt {
  char *key_seq;		/* Key sequence */
  struct {
    char *name;			/* Root menu entry to use */
    int ul;			/* Underline position */
  } root;
  struct {
    char *name;			/* Entry to use */
    int ul;			/* Underline position */
    char *gtag;			/* Grouping tag */
    int order;			/* Ordering within group */
  } entry;
  char *command;		/* Command to execute */
  short accel_label_only;	/* Use key_seq only as menu accelerator label */
} GKeyMenuEnt;

struct gateinfo {
  int		Code;		/* Code number for gate */
  char		*englishName;	/* English name */
  char		*vnames;	/* Verilog names */
  unsigned	vmask;		/* Verilog name mutating ports */
  char		*psprint;	/* Postscript display function for gate */
  char		**psdef;	/* Postscript definition for gate */

  GKeyMenuEnt cmds[MAXKBINDS];	/* Menu and keyboard shortcuts */

  iconDimensions *dim;		/* Size of gate */

  int NumPads;			/* Number of pin types */
  struct padinfo Pad[MAXWIRES];	/* Pin type descriptions */

  GLabelPos lpos[NUMORIENTS];	/* Positions of gate name labels */

  struct {
    unsigned CanRot:1;		/* Do rotations exist */
    unsigned NoInvert:1;	/* Can't put inverters on it */
    unsigned IsIOnet:1;		/* Is this an I/O net (port, ground, or vdd) */
    unsigned WireProps:1;	/* Is gate display affected by wire property changes? */
    unsigned special_move : 1;	/* Special movement method */
    unsigned single_icon : 1;	/* set if this is a single icon gate  */
  } Flags;

  char		*delayNames[MAXDELAYS];			/* Name of delay parameters */
  
  /* Function for gate creation */
  GCElement *(*MakeFunction)(EditState**,GModuleDef*,
			     int,int,int,int,const char*,int,const char**,int);
  void (*InitGate)(GCElement*);				/* Initialize new gate */
  void (*DeleteGate)(GCElement*,GModuleDef*,int);	/* Delete gate function */
  void (*GetExtents)(GCElement*,int*,int*
		     ,int*,int*,int*);			/* Get bounding box of gate */
  int (*HitDistance)(GCElement*,int,int);		/* Distance to gate from (x,y) */
  void (*DrawGate)(GCElement*,int);			/* Draw function */
  void (*MoveGate)(GCElement*,int,int);			/* Move function */
  GCElement *(*ReplicateGate)(GModuleDef*,GCElement*
			      ,int,int,unsigned);	/* Copy a gate */
  void (*AddInput)(EditState*,GCElement*);		/* Add Input to a gate */
  void (*AddOutput)(EditState*,GCElement*);		/* Add Output to a gate */
  void (*AddTri)(EditState*,GCElement*);		/* Add Tri-State pin to a gate */
  void (*ChangePin)(EditState*,GCElement*);		/* Change direction of pin */
  void (*SimStateFunc)(EditState*,GCElement*,const char*);	/* For simulator initialization */
  void (*SimHitFunc)(EditState*,GCElement*);		/* Handles sim-mode mouse hit on gate */
  void (*PSWrite)(FILE*,GModLayout*,GCElement*);	/* Write PostScript for gate */
  void (*EditProps)(GCElement*,int); 			/* Edit gate properties (new style) */
  void (*VerSave)(FILE*,GCElement*); 			/* Save in verilog format */
  void (*SetProp)(GCElement*,const char*,const void*);	/* Set property */
  void (*VersionDelta)(GCElement*,Version*);		/* Update from old version */

  /*********** members after here are initilized at run-time ***********/
  int	icon[2*NUMORIENTS];	/* Icons for each orientation */
  GDelayDef	*delay_defs;	/* Delay definitions for this primitive */
  int		num_delays;	/* Number of elements in delayNames[] */
};


char *GGateInfo_getName(GGateInfo*,int);

GGateInfo *gateinfo_lookup(const char*);
int gateinfo_variantNum(GGateInfo *gi,const char *func);
GGateInfo *gtype_get();
extern GGateInfo *GateInfo[];

#endif
