/****************************************************************************
    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.
****************************************************************************/
/*
    Simulator dependant	state.	Contains information on	the
    positions of switches and probes.  Also used to generate
    unique names for circuit elements.
*/
#ifndef __simulate_h
#define __simulate_h

/* Maxmimum reasonable size for a memory address (number of bits)*/
#define MAXMEMREASONABLE 16

/* Maximum number of breakpoints */
#define MAXBP	64

/* Maximum number of 'include' levels in scripts */
#define MAXINCLUDE	32

typedef struct error GError;

typedef struct {
  int	p;			/* Pointer to current level in include stack */
  FILE 	*f[MAXINCLUDE];		/* Open files in include stack */
  int	ln[MAXINCLUDE];		/* Current line numbers in include stack */
  int	err_count;		/* Error count */
  SHash	*bptable;		/* Symbolic breakpoint names */
  int	stop_wait;		/* Wait for simulator 'stop' before next command */
} SScriptStack;

typedef struct {
  char		*text;
  int		id;
  int		state;
} SBreakPoint;

typedef struct {
  int		active;			/* Flag indicating running simulator */
  char		simFileName[STRMAX];	/* Temp file with circuit description */
  GSimModule	*sim_root;		/* Root simulator module */

  int		no_scope;		/* Non-zero if no scope should be created */ 

  int		bp_count;		/* Global number of bps created */
  int		numBPs;			/* Number of breakpoints */
  SBreakPoint	breakpoints[MAXBP];	/* Table of breakpoints */

  SScriptStack	*script;		/* Script state */

  int		area;			/* Area reported for circuit */
  int		staticPower;		/* Static power reported for circuit */
} SimInterface;

typedef struct {
  char 		*name;		/* Name of probe */
  GNet		*net;		/* Net of probe */
  int 		x,y;		/* Position */
  GSimModule	*ss;		/* Simmodule this belongs to */
} GSimProbe;

typedef struct {
  char		*name;		/* Full name of wire */
  char		*gname;		/* Full name of gate */
  GCElement	*gate;		/* switch gate */
  unsigned	*state;		/* State of switch */
} GSimSwitch;

typedef struct {
  char		*name;		/* Full name of wire */
  char		*gname;		/* Full name of gate */
  GCElement	*gate;		/* led gate */
} GSimLed;

struct simmodule {
  GCElement	*inst;		/* Module instance in parent */
  GModuleDef	*mod;		/* Module this corresponds to */

  SHash		*probes;	/* Probes in this module instance */
  SHash		*switches;	/* Switches in this module instance */
  SHash		*leds;		/* Leds in this module instance */
  SHash		*children;	/* Child module instance */

  GSimModule	*parent;	/* Parent module instance */
};

struct error {
  int 		Num;		/* Error code number */
  char		*path;		/* Path to offending element */
  char		*message;	/* Error text */
  GCElement	*g;		/* Element associated with error */
  GWireNode	*n;		/* Wire node associated with error */
  GError	*next,*last;	/* Next and previous errors */
};

void SimInterface_init(SimInterface*);
void SimInterface_begin(SimInterface*);
void SimInterface_end(SimInterface*);
void SimInterface_drawProbes(SimInterface*);
void SimInterface_hit(SimInterface*,int x,int y,int isDoubleClick);
void SimInterface_hitRelease(SimInterface*);
void SimInterface_addDelProbe(SimInterface *si,GSimModule *sM,const char *name,GWire *w,GWireNode *n,int x,int y);
int SimInterface_probeExists(SimInterface *si,GSimModule *sM,const char *name);
void SimInterface_send(SimInterface*,const char*,...);
void SimInterface_execSimScript(SimInterface *si,FILE *f);
int SimInterface_insertBreakPoint(SimInterface *si,int idx,const char *bp);
void SimInterface_deleteBreakPoint(SimInterface *si,int idx);
void SimInterface_sendBreakPoints(SimInterface *si);
void SimInterface_seeBreak(SimInterface *si,int id);
void SimInterface_reportBreaks(SimInterface *si);
void SimInterface_clearBreaks(SimInterface *si);
void SimInterface_flushBreaks(SimInterface *si);
int SimInterface_lookupGate(SimInterface*,const char*,GSimModule **M,GCElement **g,GSimSwitch **ss);
int SimInterface_lookupWire(SimInterface*,const char*,GSimModule **M,GWire **w);
int SimInterface_command(SimInterface *si,const char *C);
void SimInterface_changeCurrentModule(GSimModule *new_sm,GSimModule *old_sm);
void SimInterface_gateError(SimInterface *si,const char *gname,const char *msg);
void SimInterface_fileError(SimInterface *si,const char *msg);
void SimInterface_wireError(SimInterface *si,const char *wname,const char *msg);

void Error_gateReport(const char *path,GCElement *g,const char *s);
void Error_nodeReport(const char *path,GWireNode *n,const char *s);
void Error_genericReport(const char *path,const char *s);
void Error_close();
void Error_purge();
EditState *Error_open(GError *err,EditState *es);
void Error_navigateToModule(EditState **es,const char *path);

void GSimModule_getNetPathName(GSimModule *M,GNet *n,char *buf);
void GSimModule_getFullPath(GSimModule *M,GCElement *g,char *buf);

GNet *sim_findNet(const char *name);
GCElement *sim_findGate(const char *name);
GModuleDef *sim_findContainingMod(const char *path);

int breakpoint_check(const char *s);

void getSimTempFile(char*);

#endif

