/*
 * Electric(tm) VLSI Design System
 *
 * File: sim.c
 * Simulation aid: main module
 * Written by: Steven M. Rubin, Static Free Software
 *
 * Copyright (c) 2000 Static Free Software.
 *
 * Electric(tm) 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.
 *
 * Electric(tm) 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 Electric(tm); see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, Mass 02111-1307, USA.
 *
 * Static Free Software
 * 4119 Alpine Road
 * Portola Valley, California 94028
 * info@staticfreesoft.com
 */

#include "config.h"
#if SIMAID

#include "global.h"
#include "egraphics.h"
#include "edialogs.h"
#include "sim.h"
#include "simals.h"
#include "usr.h"

/************************** ALS COMMANDS **************************/

/* ALS's build-actel-models command */
static COMCOMP qbuildp = {NOKEYWORD, topoffile, nextfile, NOPARAMS, NOBACKUP,
	0, " \t", M_("Actel table file to convert to library"), 0};

/* ALS's clock command */
static INTSML sim_nextcustomclock(char*, COMCOMP*[], char);
static COMCOMP clockcdurp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, sim_nextcustomclock, NOBACKUP,
	0, " \t", M_("clock: duration of this phase"), 0};
static COMCOMP clockclevp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("clock: level for this phase"), 0};
static INTSML sim_nextcustomclock(char *i, COMCOMP *j[], char c)
{ j[0] = &clockclevp; j[1] = &clockcdurp; return(2); }
static COMCOMP clockccyp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, sim_nextcustomclock, NOBACKUP,
	0, " \t", M_("clock: number of cycles (0 for infinite)"), 0};
static COMCOMP clockcstrp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("clock: strength"), 0};
static COMCOMP clockclp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("clock: random distribution"), 0};
static COMCOMP clockfp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("50/50 duty cycle frequency"), 0};
static COMCOMP clockpp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("50/50 duty cycle period"), 0};
static KEYWORD clockopt[] =
{
	{"frequency",     1,{&clockfp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"period",        1,{&clockpp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"custom",        3,{&clockclp,&clockcstrp,&clockccyp,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP clockop = {clockopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("clock options"), 0};
static COMCOMP clocknp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("node name"), 0};

/* ALS's go command */
static COMCOMP gop = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("maximum simulation time (in seconds)"), 0};

/* ALS's level command */
COMCOMP sim_alslevelsp = {NOKEYWORD, simals_topofinstances, simals_nextinstance,
	NOPARAMS, NOBACKUP, 0, " \t", M_("instance to set"), 0};
static KEYWORD levelopt[] =
{
	{"up",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"set",        1,{&sim_alslevelsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP levelp = {levelopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("level change option"), 0};

/* ALS's print command */
static COMCOMP printsp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("node to print"), 0};
static KEYWORD printopt[] =
{
	{"display",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"instances",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"netlist",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"size",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"state",          1,{&printsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"vector",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"xref",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP printp = {printopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("printing options"), 0};

/* ALS's seed command */
static KEYWORD seedopt[] =
{
	{"reset",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"no-reset",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP seedp = {seedopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("random number seed setting"), 0};

/* ALS's set command */
static COMCOMP settp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("time of node set (in seconds)"), 0};
static COMCOMP setsp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("strength of node set"), 0};
static KEYWORD setlopt[] =
{
	{"H",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"L",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"X",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP setlp = {setlopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("state level"), 0};
static COMCOMP setnp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("node name to set"), 0};

/* ALS's trace command */
static KEYWORD traceopt[] =
{
	{"on",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"off",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP tracep = {traceopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("trace state"), 0};

/* ALS's vector command */
static COMCOMP vectordtp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("time at which to delete"), 0};
static KEYWORD vectordopt[] =
{
	{"time",       1,{&vectordtp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"all",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP vectordop = {vectordopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("vector deletion option"), 0};
static COMCOMP vectordp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("node name to delete"), 0};
static COMCOMP vectorlp = {NOKEYWORD, topoffile, nextfile, NOPARAMS, NOBACKUP,
	0, " \t", M_("file name with vectors"), 0};
static COMCOMP vectorsp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("file name to save vectors"), 0};
static KEYWORD vectoropt[] =
{
	{"delete",      2,{&vectordp,&vectordop,NOKEY,NOKEY,NOKEY}},
	{"load",        1,{&vectorlp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"save",        1,{&vectorsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"new",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP vectorp = {vectoropt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("vector options"), 0};
static KEYWORD annotateopt[] =
{
	{"minimum",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"typical",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"maximum",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP annotatep = {annotateopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("annotate options"), 0};
static COMCOMP orderrp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("ordered list of trace names"), 0};
static KEYWORD orderopt[] =
{
	{"save",       0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"restore",    1,{&orderrp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP orderp = {orderopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("order options"), 0};

/* ALS's command table */
static KEYWORD sim_alsopt[] =
{
	{"annotate",           1,{&annotatep,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"build-actel-models", 1,{&qbuildp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"clock",              2,{&clocknp,&clockop,NOKEY,NOKEY,NOKEY}},
	{"erase",              0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"go",                 1,{&gop,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"help",               0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"level",              1,{&levelp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"order",              1,{&orderp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"print",              1,{&printp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"seed",               1,{&seedp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"set",                4,{&setnp,&setlp,&setsp,&settp,NOKEY}},
	{"trace",              1,{&tracep,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"vector",             1,{&vectorp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP sim_alsp = {sim_alsopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("Simulation command"), 0};

/************************** SIMULATION WINDOW COMMANDS **************************/

static COMCOMP cursorgp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("time at the extension cursor"), 0};
static COMCOMP cursorwp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("time at the main cursor"), 0};
static KEYWORD cursoropt[] =
{
	{"extension",    1,{&cursorgp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"main",         1,{&cursorwp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP cursorp = {cursoropt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("cursor color"), 0};

static COMCOMP moveap = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("distance to move (in seconds)"), 0};
static COMCOMP movesp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("distance to move (in signals)"), 0};
static KEYWORD moveopt[] =
{
	{"left",         1,{&moveap,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"right",        1,{&moveap,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"up",           1,{&movesp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"down",         1,{&movesp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP movep = {moveopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("window move option"), 0};

static COMCOMP zoomup = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("upper time of zoom"), 0};
static COMCOMP zoomlp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("lower time of zoom"), 0};
static COMCOMP zoomap = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("amount to zoom"), 0};
static KEYWORD zoomopt[] =
{
	{"window",        2,{&zoomlp,&zoomup,NOKEY,NOKEY,NOKEY}},
	{"in",            1,{&zoomap,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"out",           1,{&zoomap,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"cursor",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"all-displayed", 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP zoomp = {zoomopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("window zoom options"), 0};
static COMCOMP tracessp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("number of traces to show on the display"), 0};
static KEYWORD tracesopt[] =
{
	{"more",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"less",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"set",       1,{&tracessp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP tracesp = {tracesopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("window traces options"), 0};
static KEYWORD dispcolorsopt[] =
{
	{"white",          0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"black",          0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"red",            0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"blue",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"green",          0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"cyan",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"magenta",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"yellow",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"gray",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"orange",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"purple",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"brown",          0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"light-gray",     0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"dark-gray",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"light-red",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"dark-red",       0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"light-green",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"dark-green",     0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"light-blue",     0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"dark-blue",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP dispcolorsp = {dispcolorsopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("color for this strength/level"), 0};
static KEYWORD dispcoloropt[] =
{
	{"off",       1,{&dispcolorsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"node",      1,{&dispcolorsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"gate",      1,{&dispcolorsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"power",     1,{&dispcolorsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"low",       1,{&dispcolorsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"high",      1,{&dispcolorsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"undefined", 1,{&dispcolorsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP dispcolorp = {dispcoloropt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("window strength color options"), 0};
static KEYWORD sim_windowopt[] =
{
	{"cursor",              1,{&cursorp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"move",                1,{&movep,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"traces",              1,{&tracesp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"zoom",                1,{&zoomp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"color",               1,{&dispcolorp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"2-state-display",     0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"12-state-display",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"advance-time",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"freeze-time",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"display-waveform",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"ignore-waveform",     0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP sim_windowp = {sim_windowopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
	0, " \t", M_("Simulation window command"), 0};

/************************** SPICE COMMANDS **************************/

static KEYWORD sim_spicelevelopt[] =
{
	{"1",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"2",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"3",    0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP sim_spicelevelp = {sim_spicelevelopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Spice simulation level"), M_("show current")};
static KEYWORD sim_spiceformopt[] =
{
	{"2",                  0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"3",                  0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"hspice",             0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP sim_spiceformp = {sim_spiceformopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Spice format"), 0};
static KEYWORD sim_spicenotopt[] =
{
	{"resistance",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"capacitances",       0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"plot",               0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"use-nodenames",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP sim_spicenotp = {sim_spicenotopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Spice simulation NOT option"), 0};
COMCOMP sim_spicereadp = {NOKEYWORD, topoffile, nextfile, NOPARAMS,
	NOBACKUP, INPUTOPT, " \t", M_("File containing spice output"), 0};
static COMCOMP sim_spicesavep = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS,
	NOBACKUP, INPUTOPT, " \t", M_("File in which to save spice output"), 0};
static KEYWORD sim_spiceopt[] =
{
	{"level",              1,{&sim_spicelevelp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"save-output",        1,{&sim_spicesavep,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"format",             1,{&sim_spiceformp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"parse-output",       1,{&sim_spicereadp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"debug-toggle",       0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"not",                1,{&sim_spicenotp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"resistance",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"capacitances",       0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"plot",               0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"use-nodenames",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
COMCOMP sim_spicep = {sim_spiceopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Spice simulation option"), 0};

/************************** VERILOG COMMANDS **************************/

static KEYWORD sim_vernotopt[] =
{
	{"use-assign",              0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP sim_vernotp = {sim_vernotopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Verilog simulation NOT option"), 0};
static KEYWORD sim_veropt[] =
{
	{"not",                     1,{&sim_vernotp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"use-assign",              0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
COMCOMP sim_verp = {sim_veropt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Verilog simulation option"), 0};

/************************** FASTHENRY COMMANDS **************************/

static COMCOMP simfhaaddp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry arc group name"), 0};
static COMCOMP simfhathickp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry arc thickness"), 0};
static COMCOMP simfhawidsubp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry arc width subdivisions"), 0};
static COMCOMP simfhaheisubp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry arc height subdivisions"), 0};
static COMCOMP simfhazheadp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry arc head Z"), 0};
static COMCOMP simfhaztailp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry arc tail Z"), 0};
static KEYWORD sim_fhaopt[] =
{
	{"add",                 1,{&simfhaaddp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"remove",              0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"thickness",           1,{&simfhathickp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"width-subdivisions",  1,{&simfhawidsubp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"height-subdivisions", 1,{&simfhaheisubp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"z-head",              1,{&simfhazheadp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"z-tail",              1,{&simfhaztailp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
COMCOMP sim_fhap = {sim_fhaopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry arc option"), 0};
static COMCOMP simfhpolemp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Number of poles"), 0};
static KEYWORD simfhpoleopt[] =
{
	{"single",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"multiple",         1,{&simfhpolemp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP simfhpolep = {simfhpoleopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry multipole option"), 0};
static COMCOMP simfhfreqsp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Starting frequency"), 0};
static COMCOMP simfhfreqep = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Ending frequency"), 0};
static COMCOMP simfhfreqrp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Runs per decade"), 0};
static KEYWORD simfhfreqopt[] =
{
	{"single",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"multiple",         3,{&simfhfreqsp,&simfhfreqep,&simfhfreqrp,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP simfhfreqp = {simfhfreqopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry frequency option"), 0};
static COMCOMP simfhthickp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry default thickness"), 0};
static COMCOMP simfhwidthp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry default width subdivisions"), 0};
static COMCOMP simfhheightp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry default height subdivisions"), 0};
static COMCOMP simfhseglenp = {NOKEYWORD, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry maximum segment length"), 0};
static KEYWORD simfhexeopt[] =
{
	{"none",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"run",            0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"multiple-run",   0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP simfhexep = {simfhexeopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry execution option"), 0};
static KEYWORD simfhpsopt[] =
{
	{"on",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"off",          0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP simfhpsp = {simfhpsopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry PostScript option"), 0};
static KEYWORD simfhspiceopt[] =
{
	{"on",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"off",          0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP simfhspicep = {simfhspiceopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry Spice option"), 0};
static KEYWORD sim_fhopt[] =
{
	{"arc",                 1,{&sim_fhap,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"pole",                1,{&simfhpolep,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"frequency",           1,{&simfhfreqp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"thickness",           1,{&simfhthickp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"width-subdivisions",  1,{&simfhwidthp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"height-subdivisions", 1,{&simfhheightp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"max-segment-length",  1,{&simfhseglenp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"execute",             1,{&simfhexep,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"postscript",          1,{&simfhpsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"spice",               1,{&simfhspicep,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
COMCOMP sim_fhp = {sim_fhopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("FastHenry simulation option"), 0};

/************************** SIMULATOR COMMANDS **************************/

static KEYWORD simulatorsimulateopt[] =
{
	{"esim",             0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"rsim",             0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"rnl",              0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"cosmos",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"fasthenry",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"spice",            0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"mossim",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"texsim",           0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"als",              0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"verilog",          0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"abel-pal",         0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"silos",            0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
static COMCOMP simsimulatep = {simulatorsimulateopt, NOTOPLIST, NONEXTLIST,
	NOPARAMS, NOBACKUP, INPUTOPT, " \t", M_("Netlist format to generate"), 0};
static COMCOMP simulatornetp = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
	NOBACKUP, INPUTOPT, " \t", M_("net or component to point out"), 0};
static KEYWORD simulatoropt[] =
{
	{"spice",                    1,{&sim_spicep,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"pointout",                 1,{&simulatornetp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"als",                      1,{&sim_alsp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"verilog",                  1,{&sim_verp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"fasthenry",                1,{&sim_fhp,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"no-execute",               0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"execute-only",             0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"execute-quietly",          0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"execute-and-parse",        0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"execute-quietly-and-parse",0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"resume",                   0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"simulate",                 1,{&simsimulatep,NOKEY,NOKEY,NOKEY,NOKEY}},
	{"window",                   1,{&sim_windowp,NOKEY,NOKEY,NOKEY,NOKEY}},
	TERMKEY
};
COMCOMP sim_simulatorp = {simulatoropt,NOTOPLIST,NONEXTLIST,NOPARAMS,NOBACKUP,
		0, " \t", M_("Simulator action"), M_("show current simulator")};

struct
{
	char *simname;
	INTSML min;
	INTSML format;
} sim_simtable[] =
{
	{"abel-pal",  1, ABEL},
	{"cosmos",	  1, COSMOS},
	{"esim",      1, ESIM},
	{"fasthenry", 1, FASTHENRY},
	{"rnl",       2, RNL},
	{"rsim",      2, RSIM},
	{"mossim",    1, MOSSIM},
	{"als",       1, ALS},
	{"texsim",    1, TEXSIM},
	{"silos",     2, SILOS},
	{"spice",     2, SPICE},
	{"verilog",   1, VERILOG},
	{NULL, 0, 0}  /* 0 */
};

AIDENTRY  *sim_aid;					/* the Simulator aid object */
INTBIG     sim_format;				/* key for "SIM_format" (ESIM, etc) */
INTBIG     sim_netfile;				/* key for "SIM_netfile" */
INTBIG     sim_dontrun;				/* key for "SIM_dontrun" */
NODEPROTO *sim_simnt;				/* facet being simulated */
int        sim_tosim[2];			/* pipe to the simulator process */
int        sim_fromsim[2];			/* pipe from the simulator process */
INTBIG     sim_process;				/* process number of simulator */
INTBIG     sim_pseudonet;			/* for internal networks */
INTSML     sim_circuitchanged;		/* nonzero if circuit being simulated was changed */
INTSML     sim_undoredochange;		/* nonzero if change comes from undo/redo */
ARCINST   *sim_modifyarc;			/* arc whose userbits are being changed */
INTBIG     sim_modifyarcbits;		/* former value of userbits on changed arc */
INTBIG     sim_filetypeesim;		/* ESIM netlist file descriptor */
INTBIG     sim_filetypefasthenry;	/* FastHenry netlist file descriptor */
INTBIG     sim_filetypehspiceout;	/* HSPICE output file descriptor */
INTBIG     sim_filetypemossim;		/* MOSSIM netlist file descriptor */
INTBIG     sim_filetypepal;			/* PAL netlist file descriptor */
INTBIG     sim_filetypeals;			/* ALS netlist file descriptor */
INTBIG     sim_filetypealsvec;		/* ALS vectors file descriptor */
INTBIG     sim_filetypenetlisp;		/* Netlisp netlist file descriptor */
INTBIG     sim_filetypequisc;		/* QUISC netlist file descriptor */
INTBIG     sim_filetypersim;		/* RSIM netlist file descriptor */
INTBIG     sim_filetypesilos;		/* Silos netlist file descriptor */
INTBIG     sim_filetypespice;		/* SPICE input file descriptor */
INTBIG     sim_filetypespiceout;	/* SPICE output file descriptor */
INTBIG     sim_filetypetegas;		/* Tegas netlist file descriptor */
INTBIG     sim_filetypetegastab;	/* Tegas table file descriptor */
INTBIG     sim_filetypeverilog;		/* Verilog file descriptor */

/* Simulation Options */
DIALOGITEM sim_optionsdialogitems[] =
{
 /*  1 */ {0, {48,216,72,280}, BUTTON, N_("OK")},
 /*  2 */ {0, {8,216,32,280}, BUTTON, N_("Cancel")},
 /*  3 */ {0, {8,8,24,205}, CHECK, N_("Resimulate each change")},
 /*  4 */ {0, {32,8,48,205}, CHECK, N_("Auto advance time")},
 /*  5 */ {0, {56,8,72,205}, CHECK, N_("Multistate display")},
 /*  6 */ {0, {80,8,96,205}, CHECK, N_("Show waveform window")},
 /*  7 */ {0, {104,8,120,133}, MESSAGE, N_("Maximum events:")},
 /*  8 */ {0, {104,136,120,217}, EDITTEXT, ""}
};
DIALOG sim_optionsdialog = {{50,75,179,364}, N_("Simulation Options"), 0, 8, sim_optionsdialogitems};

/* ALS Clock */
DIALOGITEM sim_alsclockdialogitems[] =
{
 /*  1 */ {0, {8,320,32,384}, BUTTON, N_("OK")},
 /*  2 */ {0, {40,320,64,384}, BUTTON, N_("Cancel")},
 /*  3 */ {0, {16,8,32,101}, RADIO, N_("Frequency:")},
 /*  4 */ {0, {40,8,56,101}, RADIO, N_("Period:")},
 /*  5 */ {0, {80,8,96,101}, RADIO, N_("Custom:")},
 /*  6 */ {0, {28,208,44,283}, EDITTEXT, ""},
 /*  7 */ {0, {28,112,44,199}, MESSAGE, N_("Freq/Period:")},
 /*  8 */ {0, {112,236,128,384}, RADIO, N_("Gate Strength")},
 /*  9 */ {0, {236,232,252,369}, RADIO, N_("Undefined Phase")},
 /* 10 */ {0, {112,8,128,151}, MESSAGE, N_("Random Distribution:")},
 /* 11 */ {0, {112,160,128,223}, EDITTEXT, ""},
 /* 12 */ {0, {136,236,152,384}, RADIO, N_("VDD Strength (strong)")},
 /* 13 */ {0, {88,236,104,384}, RADIO, N_("Node Strength (weak)")},
 /* 14 */ {0, {212,232,228,328}, RADIO, N_("High Phase")},
 /* 15 */ {0, {292,272,308,363}, BUTTON, N_("Delete Phase")},
 /* 16 */ {0, {164,8,279,221}, SCROLL|INACTIVE, ""},
 /* 17 */ {0, {164,224,180,288}, MESSAGE, N_("Duration:")},
 /* 18 */ {0, {264,272,280,363}, BUTTON, N_("Add Phase")},
 /* 19 */ {0, {292,8,308,197}, MESSAGE, N_("Phase Cycles (0 for infinite):")},
 /* 20 */ {0, {292,200,308,247}, EDITTEXT, ""},
 /* 21 */ {0, {164,296,180,369}, EDITTEXT, ""},
 /* 22 */ {0, {148,8,164,99}, MESSAGE, N_("Phase List:")},
 /* 23 */ {0, {188,232,204,327}, RADIO, N_("Low Phase")},
 /* 24 */ {0, {72,8,73,384}, DIVIDELINE, ""}
};
DIALOG sim_alsclockdialog = {{50,75,367,468}, N_("Clock Specification"), 0, 24, sim_alsclockdialogitems};

/* SPICE Options */
DIALOGITEM sim_spiceoptdialogitems[] =
{
 /*  1 */ {0, {48,420,72,480}, BUTTON, N_("OK")},
 /*  2 */ {0, {8,420,32,480}, BUTTON, N_("Cancel")},
 /*  3 */ {0, {56,8,72,188}, POPUP, ""},
 /*  4 */ {0, {8,96,24,187}, POPUP, ""},
 /*  5 */ {0, {428,216,444,375}, RADIO, N_("Use Model from File:")},
 /*  6 */ {0, {404,216,420,426}, RADIO, N_("Derive Model from Circuitry")},
 /*  7 */ {0, {32,96,48,140}, POPUP, "1"},
 /*  8 */ {0, {428,384,444,423}, BUTTON, N_("Set")},
 /*  9 */ {0, {452,224,484,480}, MESSAGE, ""},
 /* 10 */ {0, {32,240,48,372}, CHECK, N_("Use Node Names")},
 /* 11 */ {0, {8,240,24,359}, CHECK, N_("Use Parasitics")},
 /* 12 */ {0, {8,8,24,93}, MESSAGE, N_("File Format:")},
 /* 13 */ {0, {32,8,48,93}, MESSAGE, N_("SPICE Level:")},
 /* 14 */ {0, {120,16,136,200}, RADIO, N_("Use Built-in Model Cards")},
 /* 15 */ {0, {144,16,160,213}, RADIO, N_("Use Model Cards from File:")},
 /* 16 */ {0, {144,216,176,480}, MESSAGE, ""},
 /* 17 */ {0, {192,16,208,140}, RADIO, N_("No Trailer Cards")},
 /* 18 */ {0, {216,16,232,202}, RADIO, N_("Include Trailer from File:")},
 /* 19 */ {0, {216,208,248,480}, MESSAGE, ""},
 /* 20 */ {0, {96,8,112,209}, MESSAGE, ""},
 /* 21 */ {0, {160,32,176,163}, BUTTON, N_("Set Model Card File")},
 /* 22 */ {0, {232,32,248,163}, BUTTON, N_("Set Trailer Card File")},
 /* 23 */ {0, {404,8,500,206}, SCROLL, ""},
 /* 24 */ {0, {388,8,404,80}, MESSAGE, N_("For Facet:")},
 /* 25 */ {0, {120,216,136,403}, BUTTON, N_("Edit Built-in Model Cards")},
 /* 26 */ {0, {84,8,85,480}, DIVIDELINE, ""},
 /* 27 */ {0, {376,8,377,480}, DIVIDELINE, ""},
 /* 28 */ {0, {260,80,340,274}, SCROLL, ""},
 /* 29 */ {0, {264,16,280,76}, MESSAGE, N_("Layer:")},
 /* 30 */ {0, {260,280,276,372}, MESSAGE, N_("Resistance:")},
 /* 31 */ {0, {284,280,300,372}, MESSAGE, N_("Capacitance:")},
 /* 32 */ {0, {308,280,324,372}, MESSAGE, N_("Edge Cap:")},
 /* 33 */ {0, {260,380,276,480}, EDITTEXT, ""},
 /* 34 */ {0, {284,380,300,480}, EDITTEXT, ""},
 /* 35 */ {0, {308,380,324,480}, EDITTEXT, ""},
 /* 36 */ {0, {348,16,364,132}, MESSAGE, N_("Min. Resistance:")},
 /* 37 */ {0, {348,136,364,224}, EDITTEXT, ""},
 /* 38 */ {0, {348,272,364,388}, MESSAGE, N_("Min. Capacitance:")},
 /* 39 */ {0, {348,392,364,480}, EDITTEXT, ""}
};
DIALOG sim_spiceoptdialog = {{50,75,559,565}, N_("SPICE Options"), 0, 39, sim_spiceoptdialogitems};

/* Verilog Options */
DIALOGITEM sim_verilogoptdialogitems[] =
{
 /*  1 */ {0, {12,408,36,466}, BUTTON, N_("OK")},
 /*  2 */ {0, {12,324,36,382}, BUTTON, N_("Cancel")},
 /*  3 */ {0, {72,216,88,375}, RADIO, N_("Use Model from File:")},
 /*  4 */ {0, {48,216,64,426}, RADIO, N_("Derive Model from Circuitry")},
 /*  5 */ {0, {72,392,88,431}, BUTTON, N_("Set")},
 /*  6 */ {0, {96,224,128,480}, MESSAGE, ""},
 /*  7 */ {0, {8,8,24,180}, CHECK, N_("Use ASSIGN Construct")},
 /*  8 */ {0, {48,8,144,206}, SCROLL, ""},
 /*  9 */ {0, {32,8,48,80}, MESSAGE, N_("For Facet:")}
};
DIALOG sim_verilogoptdialog = {{50,75,203,564}, N_("Verilog Options"), 0, 9, sim_verilogoptdialogitems};

/* prototypes for local routines */
void sim_checktostopsimulation(NODEPROTO *np);
void sim_writephases(float[], INTBIG[], INTBIG);
void sim_optionsdlog(void);
void sim_spicedlog(void);
void sim_verilogdlog(void);

void sim_init(INTBIG *argc, char *argv[], AIDENTRY *thisaid)
{
	/* nothing on pass 2 or 3 of initialization */
	if (thisaid == NOAID || thisaid == 0) return;

	/* pass 1 initialization */
	sim_aid = thisaid;
	sim_format = makekey("SIM_format");
	sim_dontrun = makekey("SIM_dontrun");
	sim_netfile = makekey("SIM_netfile");
	sim_window_state = makekey("SIM_window_state");

	/* create disk file descriptors ("sim_filetypehspiceout" is not used!!!) */
	sim_filetypeesim = setupfiletype("sim", "*.sim", MACFSTAG('TEXT'), 0, "esim", _("ESIM netlist"));
	sim_filetypefasthenry = setupfiletype("inp", "*.inp", MACFSTAG('TEXT'), 0, "fasthenry", _("FastHenry netlist"));
	sim_filetypehspiceout = setupfiletype("tr0", "*.tr0", MACFSTAG('TEXT'), 0, "hspiceout", _("HSPICE output"));
	sim_filetypemossim = setupfiletype("ntk", "*.ntk", MACFSTAG('TEXT'), 0, "mossim", _("MOSSIM netlist"));
	sim_filetypepal = setupfiletype("pal", "*.pal", MACFSTAG('TEXT'), 0, "pal", _("Abel PAL"));
	sim_filetypeals = setupfiletype("net", "*.net", MACFSTAG('TEXT'), 0, "als", _("ALS netlist"));
	sim_filetypealsvec = setupfiletype("vec", "*.vec", MACFSTAG('TEXT'), 0, "alsvec", _("ALS vector"));
	sim_filetypenetlisp = setupfiletype("net", "*.net", MACFSTAG('TEXT'), 0, "netlisp", _("NetLisp netlist"));
	sim_filetypequisc = setupfiletype("sci", "*.sci", MACFSTAG('TEXT'), 0, "quisc", _("QUISC netlist"));
	sim_filetypersim = setupfiletype("sim", "*.sim", MACFSTAG('TEXT'), 0, "rsim", _("RSIM netlist"));
	sim_filetypesilos = setupfiletype("sil", "*.sil", MACFSTAG('TEXT'), 0, "silos", _("SILOS netlist"));
	sim_filetypespice = setupfiletype("spi", "*.spi;*.spo", MACFSTAG('TEXT'), 0, "spice", _("SPICE netlist"));
	sim_filetypespiceout = setupfiletype("spo", "*.spo", MACFSTAG('TEXT'), 0, "spiceout", _("SPICE output"));
	sim_filetypetegas = setupfiletype("tdl", "*.tdl", MACFSTAG('TEXT'), 0, "tegas", _("TEGAS netlist"));
	sim_filetypetegastab = setupfiletype("", "*.*", MACFSTAG('TEXT'), 0, "tegastab", _("TEGAS table"));
	sim_filetypeverilog = setupfiletype("v", "*.v;*.ver", MACFSTAG('TEXT'), 0, "verilog", _("Verilog"));

	/* initialize default simulator format */
	nextvarchangequiet();
	(void)setvalkey((INTBIG)sim_aid, VAID, sim_format, ALS, VINTEGER|VDONTSAVE);

	/* do not have the simulator automatically run */
	nextvarchangequiet();
	(void)setvalkey((INTBIG)sim_aid, VAID, sim_dontrun, SIMRUNNO, VINTEGER|VDONTSAVE);

	/* ESIM/RSIM/RNL initialization */
	nextvarchangequiet();
	(void)setvalkey((INTBIG)sim_aid, VAID, sim_netfile, (INTBIG)"", VSTRING|VDONTSAVE);

	/* SPICE initialization */
	sim_listingfile = makekey("SIM_listingfile");
	sim_spice_level = makekey("SIM_spice_level");
	sim_spice_state = makekey("SIM_spice_state");
	nextvarchangequiet();
	(void)setvalkey((INTBIG)sim_aid, VAID, sim_listingfile, (INTBIG)"", VSTRING|VDONTSAVE);
	nextvarchangequiet();
	(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state, SPICERESISTANCE|SPICE3, VINTEGER);
	nextvarchangequiet();
	(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_level, 1, VINTEGER);
	DiaDeclareHook("spice", &sim_spicep, sim_spicedlog);

	/* VERILOG initialization */
	sim_verilog_state = makekey("SIM_verilog_state");
	DiaDeclareHook("verilog", &sim_verp, sim_verilogdlog);

	/* FastHenry initialization */
	sim_fasthenrystatekey = makekey("SIM_fasthenry_state");
	sim_fasthenryfreqstartkey = makekey("SIM_fasthenry_freqstart");
	sim_fasthenryfreqendkey = makekey("SIM_fasthenry_freqend");
	sim_fasthenryrunsperdecadekey = makekey("SIM_fasthenry_runsperdecade");
	sim_fasthenrynumpoleskey = makekey("SIM_fasthenry_numpoles");
	sim_fasthenryseglimitkey = makekey("SIM_fasthenry_seglimit");
	sim_fasthenrythicknesskey = makekey("SIM_fasthenry_thickness");
	sim_fasthenrywidthsubdivkey = makekey("SIM_fasthenry_width_subdivs");
	sim_fasthenryheightsubdivkey = makekey("SIM_fasthenry_height_subdivs");
	sim_fasthenryzheadkey = makekey("SIM_fasthenry_z_head");
	sim_fasthenryztailkey = makekey("SIM_fasthenry_z_tail");
	sim_fasthenrygroupnamekey = makekey("SIM_fasthenry_group_name");
	sim_fasthenryinit();

	/* initialize the simulation window system */
	sim_window_init();

	/* miscellaneous initialization */
	sim_process = -1;
	sim_simnt = NONODEPROTO;
	sim_circuitchanged = 0;
	sim_undoredochange = 0;
	DiaDeclareHook("simopt", &sim_simulatorp, sim_optionsdlog);
}

void sim_done(void)
{
	REGISTER VARIABLE *var;

	if (sim_process >= 0)
	{
		ekill(sim_process);
		ewait(sim_process);

		var = getvalkey((INTBIG)sim_aid, VAID, VSTRING, sim_netfile);
		if (var != NOVARIABLE)
			ttyputmsg(_("Simulation net list saved in '%s'"), (char *)var->addr);
	}

	/* free all memory */
	simals_term();
	sim_window_term();
	sim_freespicememory();
}

INTSML sim_set(INTSML count, char *par[])
{
	REGISTER INTSML i, l, newformat, amount, signals, curtop, vis;
	REGISTER INTBIG spicestate, verilogstate, windowstate, options, value;
	float fvalue;
	REGISTER char *pp;
	REGISTER VARIABLE *var;
	REGISTER ARCINST *ai;
	NODEPROTO *np;
	NODEPROTO *simnp;
	REGISTER INTSML active;
	extern AIDENTRY *vhdl_aid;
	float time, size, factor, maxtime, mintime, maintime, extensiontime;

	if (count == 0)
	{
		var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_format);
		if (var == NOVARIABLE) l = -1; else l = (INTSML)var->addr;
		for(i=0; sim_simtable[i].simname != 0; i++)
			if (l == sim_simtable[i].format)
		{
			ttyputmsg(_("Current simulator is %s"), sim_simtable[i].simname);
			if (l == ESIM || l == RSIM || l == RNL || l == SPICE)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_dontrun);
				if (var != NOVARIABLE)
				{
					if (var->addr == SIMRUNYESPARSE)
					{
						ttyputmsg(_("After writing netlist, simulator will run and output will be parsed"));
						return(0);
					}
					if (var->addr == SIMRUNYES)
					{
						ttyputmsg(_("After writing netlist, simulator will be run"));
						return(0);
					}
					if (var->addr == SIMRUNYESQPARSE)
					{
						ttyputmsg(_("After writing netlist, simulator will run quietly and output will be parsed"));
						return(0);
					}
					if (var->addr == SIMRUNYESQ)
					{
						ttyputmsg(_("After writing netlist, simulator will run quietly"));
						return(0);
					}
				}
			}
			ttyputmsg(_("Only netlist will be written, no simulator will be run"));
			return(0);
		}
		ttyputmsg(_("No current simulator"));
		return(0);
	}
	l = strlen(pp = par[0]);

	if (namesamen(pp, "simulate", l) == 0 && l >= 2)
	{
		if (count < 2)
		{
			ttyputusage("tellaid simulation simulate FORMAT");
			return(1);
		}

		/* get the simulator name */
		l = strlen(pp = par[1]);
		for(i=0; sim_simtable[i].simname != 0; i++)
			if (namesamen(pp, sim_simtable[i].simname, l) == 0 && l >= sim_simtable[i].min) break;
		if (sim_simtable[i].simname == 0)
		{
			ttyputbadusage("tellaid simulation simulate");
			return(1);
		}
		newformat = sim_simtable[i].format;

		/* see if there is already a simulation running */
		if (sim_process != -1)
		{
			var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_format);
			if (var != NOVARIABLE && newformat == var->addr)
			{
				ttyputmsg(_("This simulator is already running"));
				return(0);
			}
			ttyputerr(_("Cannot switch simulators while one is running"));
			return(1);
		}

		/* make sure there is a facet to simulate */
		np = getcurfacet();
		if (np == NONODEPROTO)
		{
			ttyputerr(_("No current facet to simulate"));
			return(1);
		}

		/* remember the currently running format */
		(void)setvalkey((INTBIG)sim_aid, VAID, sim_format, newformat, VINTEGER|VDONTSAVE);

		/* write the appropriate simulation file */
		switch (newformat)
		{
			case ABEL:
				sim_writepalnetlist(np);
				break;
			case FASTHENRY:
				sim_writefasthenrynetlist(np);
				break;
			case COSMOS:
			case ESIM:
			case RNL:
			case RSIM:
				sim_writesim(np, newformat);
				break;
			case MOSSIM:
				sim_writemossim(np);
				break;
			case ALS:
				active = sim_window_isactive(&simnp);
				if (active != 0)
				{
					if (simnp == np)
					{
						/* display schematic window if it is not up */
						if ((active&SIMWINDOWSCHEMATIC) == 0)
						{
							(void)sim_window_create(0, simnp, 0, simals_charhandlerschem);
							break;
						}

						/* display waveform window if it is not up */
						var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_window_state);
						if (var == NOVARIABLE) windowstate = 0; else windowstate = var->addr;
						if ((active&SIMWINDOWWAVEFORM) == 0 && (windowstate&SHOWWAVEFORM) != 0)
						{
							(void)sim_window_create(0, simnp, simals_charhandlerwave, 0);
							break;
						}
						ttyputmsg(_("Simulation is already running"));
						break;
					}
					ttyputerr(_("Close all simulation windows before simulating another facet"));
					break;
				}

				/* do not simulate icons */
				if (np->cellview == el_iconview)
				{
					ttyputerr(_("Cannot simulate an icon"));
					break;
				}

				/* initialize memory */
				simals_init();

				/* demand a ALS netlist */
				(void)askaid(vhdl_aid, "want-netlist-input", (INTBIG)np, sim_filetypeals);

				/* read netlist */
				simals_erase_model();
				if (simals_read_net_desc(np) != 0) break;
				if (simals_flatten_network() != 0) break;

				/* initialize display */
				simals_init_display();

				/* turn on this tool so that it can track changes to original circuit */
				aidturnon(sim_aid, 1);
				break;
			case SILOS:
				sim_writesilnetlist(np);
				break;
			case SPICE:
				sim_writespice(np);
				break;
			case TEXSIM:
				sim_writetexnetlist(np);
				break;
			case VERILOG:
				sim_writevernetlist(np);
				break;
		}
		return(0);
	}

	if (namesamen(pp, "resume", l) == 0 && l >= 1)
	{
		var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_format);
		if (var == NOVARIABLE)
		{
			ttyputerr(_("No simulation is running"));
			return(1);
		}
		switch (var->addr)
		{
			case RNL:
			case RSIM:
			case ESIM:
				sim_resumesim(0);
				break;
			default:
				ttyputerr(_("Cannot resume this simulator"));
				break;
		}
		return(0);
	}

	if (namesamen(pp, "no-execute", l) == 0 && l >= 1)
	{
		(void)setvalkey((INTBIG)sim_aid, VAID, sim_dontrun, SIMRUNNO, VINTEGER);
		ttyputmsg(_("Simulator will not be invoked (deck generation only)"));
		return(0);
	}
	if (namesamen(pp, "execute-only", l) == 0 && l >= 9)
	{
		(void)setvalkey((INTBIG)sim_aid, VAID, sim_dontrun, SIMRUNYES, VINTEGER);
		ttyputmsg(_("Simulator will be invoked"));
		return(0);
	}
	if (namesamen(pp, "execute-and-parse", l) == 0 && l >= 9)
	{
		(void)setvalkey((INTBIG)sim_aid, VAID, sim_dontrun, SIMRUNYESPARSE, VINTEGER);
		ttyputmsg(_("Simulator will be invoked, output parsed"));
		return(0);
	}
	if (namesamen(pp, "execute-quietly-and-parse", l) == 0 && l >= 16)
	{
		(void)setvalkey((INTBIG)sim_aid, VAID, sim_dontrun, SIMRUNYESQPARSE, VINTEGER);
		ttyputmsg(_("Simulator will be invoked quietly, output parsed"));
		return(0);
	}
	if (namesamen(pp, "execute-quietly", l) == 0 && l >= 9)
	{
		(void)setvalkey((INTBIG)sim_aid, VAID, sim_dontrun, SIMRUNYESQ, VINTEGER);
		ttyputmsg(_("Simulator will be invoked quietly, output parsed"));
		return(0);
	}

	if (namesamen(pp, "pointout", l) == 0 && l >= 1)
	{
		if (count <= 1)
		{
			ttyputusage("tellaid simulation pointout ELEMENT");
			return(1);
		}
		var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_format);
		if (var != NOVARIABLE) switch (var->addr)
		{
			case RNL:
			case RSIM:
			case ESIM:
			case COSMOS: return(sim_simpointout(par[1], (INTSML)(var->addr)));
		}
		ttyputerr(_("Current simulator cannot pointout netlist objects"));
		return(1);
	}

	if (namesamen(pp, "window", l) == 0 && l >= 1)
	{
		if (count <= 1)
		{
			ttyputusage("tellaid simulation window COMMAND");
			return(1);
		}
		var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_window_state);
		if (var == NOVARIABLE) windowstate = 0; else windowstate = var->addr;
		l = strlen(pp = par[1]);
		if (namesamen(pp, "2-state-display", l) == 0 && l >= 1)
		{
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_window_state,
				windowstate & ~FULLSTATE, VINTEGER);
			ttyputverbose(_("Simulation will show only 2 states in schematics window"));
			return(0);
		}
		if (namesamen(pp, "12-state-display", l) == 0 && l >= 1)
		{
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_window_state,
				windowstate | FULLSTATE, VINTEGER);
			ttyputverbose(_("Simulation will show all 12 states in schematics window"));
			return(0);
		}
		if (namesamen(pp, "advance-time", l) == 0 && l >= 1)
		{
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_window_state,
				windowstate | ADVANCETIME, VINTEGER);
			ttyputverbose(_("State changes will advance time to end of activity"));
			return(0);
		}
		if (namesamen(pp, "freeze-time", l) == 0 && l >= 1)
		{
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_window_state,
				windowstate & ~ADVANCETIME, VINTEGER);
			ttyputverbose(_("State changes will not advance time"));
			return(0);
		}
		if (namesamen(pp, "display-waveform", l) == 0 && l >= 1)
		{
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_window_state,
				windowstate | SHOWWAVEFORM, VINTEGER);
			ttyputverbose(_("Simulation will show waveform window"));
			return(0);
		}
		if (namesamen(pp, "ignore-waveform", l) == 0 && l >= 1)
		{
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_window_state,
				windowstate & ~SHOWWAVEFORM, VINTEGER);
			ttyputverbose(_("Simulation will not show waveform window"));
			return(0);
		}
		if (namesamen(pp, "color", l) == 0 && l >= 2)
		{
			if (count <= 2)
			{
				sim_window_displaycolor(99, 0);
				return(0);
			}
			l = strlen(pp = par[2]);
			if (count < 4)
			{
				ttyputusage("tellaid simulation window color SIGNAL COLORNAME");
				return(1);
			}
			i = getecolor(par[3]);
			if (i < 0)
			{
				ttyputbadusage("tellaid simulation window color");
				return(1);
			}
			if (namesamen(pp, "off", l) == 0)
			{
				sim_window_displaycolor(OFF_STRENGTH, i);
				return(0);
			}
			if (namesamen(pp, "node", l) == 0)
			{
				sim_window_displaycolor(NODE_STRENGTH, i);
				return(0);
			}
			if (namesamen(pp, "gate", l) == 0)
			{
				sim_window_displaycolor(GATE_STRENGTH, i);
				return(0);
			}
			if (namesamen(pp, "power", l) == 0)
			{
				sim_window_displaycolor(VDD_STRENGTH, i);
				return(0);
			}
			if (namesamen(pp, "low", l) == 0)
			{
				sim_window_displaycolor(LOGIC_LOW, i);
				return(0);
			}
			if (namesamen(pp, "high", l) == 0)
			{
				sim_window_displaycolor(LOGIC_HIGH, i);
				return(0);
			}
			if (namesamen(pp, "undefined", l) == 0)
			{
				sim_window_displaycolor(LOGIC_X, i);
				return(0);
			}
			ttyputbadusage("tellaid simulation window color");
			return(1);
		}
		if (namesamen(pp, "cursor", l) == 0 && l >= 2)
		{
			if (sim_window_isactive(&np) == 0)
			{
				ttyputerr(_("No simulator active"));
				return(1);
			}
			if (count < 4)
			{
				ttyputusage("tellaid simulation window cursor WHICH TIME");
				return(1);
			}
			time = (float)atof(par[3]);
			if (time < 0.0)
			{
				ttyputerr(_("Warning: time cannot be negative, set to 0 sec."));
				time = 0.0;
			}
			if (namesamen(par[2], "main", strlen(par[2])) == 0)
			{
				sim_window_setmaincursor(time);
				return(0);
			}
			if (namesamen(par[2], "extension", strlen(par[2])) == 0)
			{
				sim_window_setextensioncursor(time);
				return(0);
			}
			ttyputbadusage("tellaid simulation window cursor");
			return(1);
		}
		if (namesamen(pp, "move", l) == 0 && l >= 1)
		{
			if ((sim_window_isactive(&np)&SIMWINDOWWAVEFORM) == 0)
			{
				ttyputerr(_("No simulator waveform window is active"));
				return(1);
			}
			if (count < 3)
			{
				ttyputusage("tellaid simulation window move (left | right | up | down) [AMOUNT]");
				return(1);
			}

			l = strlen(pp = par[2]);
			if (namesamen(pp, "left", l) == 0 || namesamen(pp, "right", l) == 0)
			{
				sim_window_gettimerange(&mintime, &maxtime);
				size = maxtime - mintime;
				if (count < 4) time = size / 2.0f; else
				{
					time = (float)atof(par[3]);
					if (time <= 0.0)
					{
						ttyputerr(_("Window movement time must be greater than 0 seconds"));
						return(1);
					}
				}

				if (namesamen(pp, "left", l) == 0)
				{
					mintime -= time;
					if (mintime < 0.0) mintime = 0.0;
				} else
				{
					mintime += time;
				}
				maxtime = mintime + size;
				sim_window_settimerange(mintime, maxtime);
				sim_window_redraw();
				return(0);
			}
			if (namesamen(pp, "up", l) == 0 || namesamen(pp, "down", l) == 0)
			{
				curtop = sim_window_gettopline();
				vis = sim_window_getvislines();
				signals = sim_window_getlines();
				if (count < 4) amount = vis-1; else
				{
					amount = (INTSML)myatoi(par[3]);
					if (amount <= 0)
					{
						ttyputerr(_("Window movement time must be greater than 0 signals"));
						return(1);
					}
				}
				if (namesamen(pp, "down", l) == 0)
				{
					curtop -= amount;
					if (curtop < 0) curtop = 0;
				} else
				{
					curtop += amount;
					if (curtop + vis > signals) curtop = signals - vis;
				}
				sim_window_settopline(curtop);
				sim_window_redraw();
				return(0);
			}

			ttyputbadusage("tellaid simulation window move");
			return(1);
		}
		if (namesamen(pp, "traces", l) == 0 && l >= 1)
		{
			if ((sim_window_isactive(&np)&SIMWINDOWWAVEFORM) == 0)
			{
				ttyputerr(_("No simulator waveform window is active"));
				return(1);
			}
			if (count < 3)
			{
				ttyputusage("tellaid simulation window traces (more | less | set A)");
				return(1);
			}
			l = strlen(pp = par[2]);

			if (namesamen(pp, "more", l) == 0)
			{
				sim_window_setlines((INTSML)(sim_window_getlines()+1));
				sim_window_redraw();
				return(0);
			}
			if (namesamen(pp, "less", l) == 0)
			{
				i = sim_window_getlines();
				if (i <= 1)
				{
					ttyputerr(_("Must be at least 1 signal on the display"));
					return(1);
				}
				sim_window_setlines((INTSML)(i+1));
				sim_window_redraw();
				return(0);
			}
			if (namesamen(pp, "set", l) == 0)
			{
				if (count < 4)
				{
					ttyputusage("tellaid simulation window traces set AMOUNT");
					return(1);
				}
				i = (INTSML)myatoi(par[3]);
				if (i < 1)
				{
					ttyputerr(_("Must be at least 1 signal on the display"));
					return(1);
				}
				sim_window_setlines(i);
				sim_window_redraw();
				return(0);
			}
			ttyputbadusage("tellaid simulation window traces");
			return(1);
		}
		if (namesamen(pp, "zoom", l) == 0 && l >= 1)
		{
			if ((sim_window_isactive(&np)&SIMWINDOWWAVEFORM) == 0)
			{
				ttyputerr(_("No simulator waveform window is active"));
				return(1);
			}
			if (count < 3)
			{
				ttyputusage("tellaid simulation window zoom (in | out | window | cursor)");
				return(1);
			}
			l = strlen(pp = par[2]);

			if (namesamen(pp, "cursor", l) == 0)
			{
				maintime = sim_window_getmaincursor();
				extensiontime = sim_window_getextensioncursor();
				if (maintime == extensiontime) return(0);
				if (maintime > extensiontime)
				{
					size = (maintime-extensiontime) / 20.0f;
					maxtime = maintime + size;
					mintime = extensiontime - size;
				} else
				{
					size = (extensiontime-maintime) / 20.0f;
					maxtime = extensiontime + size;
					mintime = maintime - size;
				}
				sim_window_settimerange(mintime, maxtime);
				sim_window_redraw();
				return(0);
			}

			if (namesamen(pp, "in", l) == 0)
			{
				if (count < 4) factor = 2.0; else
				{
					factor = (float)myatoi(par[3]);
					if (factor <= 1)
					{
						ttyputerr(_("Zoom factor must be integer greater than 1"));
						return(1);
					}
				}

				sim_window_gettimerange(&mintime, &maxtime);
				size = (maxtime - mintime) / factor;
				mintime = sim_window_getmaincursor() - (size / 2.0f);
				if (mintime < 0.0) mintime = 0.0;
				maxtime = mintime + size;
				sim_window_settimerange(mintime, maxtime);
				sim_window_redraw();
				return(0);
			}

			if (namesamen(pp, "out", l) == 0)
			{
				if (count < 4) factor = 2.0; else
				{
					factor = (float)myatoi(par[3]);
					if (factor <= 1)
					{
						ttyputerr(_("Zoom factor must be integer greater than 1"));
						return(1);
					}
				}

				sim_window_gettimerange(&mintime, &maxtime);
				size = (maxtime - mintime) * factor;
				mintime = sim_window_getmaincursor() - (size / 2.0f);
				if (mintime < 0.0) mintime = 0.0;
				maxtime = mintime + size;
				sim_window_settimerange(mintime, maxtime);
				sim_window_redraw();
				return(0);
			}
			if (namesamen(pp, "all-displayed", l) == 0)
			{
				sim_window_gettimeextents(&mintime, &maxtime);
				sim_window_settimerange(mintime, maxtime);
				sim_window_redraw();
				return(0);
			}
			if (namesamen(pp, "window", l) == 0)
			{
				if (count < 4)
				{
					ttyputusage("tellaid simulation window zoom window MIN [MAX]");
					return(1);
				}

				mintime = (float)atof(par[3]);
				maxtime = 0.0;
				if (count > 4) maxtime = (float)atof(par[4]);
				if (mintime == maxtime)
				{
					ttyputerr(_("ERROR: Window size must be greater than 0"));
					return(1);
				}
				if (mintime > maxtime)
				{
					time = maxtime;
					maxtime = mintime;
					mintime = time;
				}
				sim_window_settimerange(mintime, maxtime);
				sim_window_redraw();
				return(0);
			}

			ttyputbadusage("tellaid simulation window zoom");
			return(1);
		}
		ttyputbadusage("tellaid simulation window");
		return(1);
	}

	if (namesamen(pp, "als", l) == 0 && l >= 1)
	{
		simals_com_comp((INTSML)(count-1), &par[1]);
		return(0);
	}

	if (namesamen(pp, "spice", l) == 0 && l >= 2)
	{
		l = strlen(pp = par[1]);
		if (namesamen(pp, "level", l) == 0)
		{
			if (count >= 3)
			{
				i = atoi(par[2]);
				if (i <= 0 || i > MAXSPICELEVEL) i = 1;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_level, i, VINTEGER);
			}
			var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_level);
			if (var == NOVARIABLE) i = 1; else i = (INTSML)var->addr;
			ttyputverbose(_("Simulation level set to %d"), i);
			return(0);
		}
		if (namesamen(pp, "save-output", l) == 0)
		{
			if (count < 3)
			{
				ttyputerr(_("Should supply a file name to write"));
				par[2] = "electric_def.spo";
			}
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_listingfile, (INTBIG)par[2], VSTRING|VDONTSAVE);
			ttyputverbose(_("Simulation output will go to file %s"), par[2]);
			return(0);
		}
		if (namesamen(pp, "format", l) == 0)
		{
			var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_state);
			if (var != NOVARIABLE) spicestate = var->addr; else spicestate = 0;
			if (count <= 2)
			{
				switch(spicestate&SPICETYPE)
				{
					case SPICE2:      ttyputmsg(_("SPICE decks for SPICE 2"));   break;
					case SPICE3:      ttyputmsg(_("SPICE decks for SPICE 3"));   break;
					case SPICEHSPICE: ttyputmsg(_("SPICE decks for HSPICE"));    break;
				}
				return(0);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "2", l) == 0)
			{
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
					(spicestate & ~SPICETYPE) | SPICE2, VINTEGER);
				return(0);
			}
			if (namesamen(pp, "3", l) == 0)
			{
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
					(spicestate & ~SPICETYPE) | SPICE3, VINTEGER);
				return(0);
			}
			if (namesamen(pp, "hspice", l) == 0)
			{
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
					(spicestate & ~SPICETYPE) | SPICEHSPICE, VINTEGER);
				return(0);
			}
		}
		if (namesamen(pp, "parse-output", l) == 0)
		{
			if (count < 3)
			{
				ttyputerr(_("Must supply a SPICE output file to read"));
				return(1);
			}
			sim_spice_execute("", par[2]);
			return(0);
		}
		if (namesamen(pp, "not", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation spice not OPTION");
				return(1);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "resistance", l) == 0 || namesamen(pp, "capacitances", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_state);
				if (var != NOVARIABLE)
					(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
						var->addr & ~SPICERESISTANCE, VINTEGER);
				ttyputverbose(_("SPICE decks will not print parasitics"));
				return(0);
			}
			if (namesamen(pp, "plot", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_state);
				if (var != NOVARIABLE)
					(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
						var->addr & ~SPICEPLOT, VINTEGER);
				ttyputverbose(_("SPICE decks will not do plots"));
				return(0);
			}
			if (namesamen(pp, "use-nodenames", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_state);
				if (var != NOVARIABLE)
					(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
						var->addr & ~SPICENODENAMES, VINTEGER);
				ttyputverbose(_("SPICE decks will contain node numbers"));
				return(0);
			}
			ttyputbadusage("tellaid simulation spice not");
			return(1);
		}
		if (namesamen(pp, "resistance", l) == 0 || namesamen(pp, "capacitances", l) == 0)
		{
			var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_state);
			if (var != NOVARIABLE)
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
					var->addr | SPICERESISTANCE, VINTEGER);
			ttyputverbose(_("SPICE decks will print parasitics"));
			return(0);
		}
		if (namesamen(pp, "plot", l) == 0)
		{
			var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_state);
			if (var != NOVARIABLE)
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
					var->addr | SPICEPLOT, VINTEGER);
			ttyputverbose(_("SPICE decks will do plots"));
			return(0);
		}
		if (namesamen(pp, "debug-toggle", l) == 0)
		{
			if ((sim_spice_debug&SPICEDEBUG) == 0)
			{
				sim_spice_debug |= SPICEDEBUG;
				ttyputverbose(_("SPICE deck generation debugging output on"));
			} else
			{
				sim_spice_debug &= ~SPICEDEBUG;
				ttyputverbose(_("SPICE deck generation debugging output off"));
			}
			return(0);
		}
		if (namesamen(pp, "use-nodenames", l) == 0)
		{
			var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_state);
			if (var != NOVARIABLE)
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state,
					var->addr | SPICENODENAMES, VINTEGER);
			ttyputverbose(_("SPICE decks will contain node names"));
			return(0);
		}
		ttyputbadusage("tellaid simulation spice");
		return(1);
	}

	if (namesamen(pp, "verilog", l) == 0 && l >= 1)
	{
		l = strlen(pp = par[1]);
		if (namesamen(pp, "use-assign", l) == 0)
		{
			var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_verilog_state);
			if (var != NOVARIABLE) verilogstate = var->addr; else
				verilogstate = 0;
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_verilog_state,
				verilogstate | VERILOGUSEASSIGN, VINTEGER);
			ttyputverbose(_("Verilog decks will use the 'assign' construct"));
			return(0);
		}
		if (namesamen(pp, "not", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation verilog not OPTION");
				return(1);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "use-assign", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_verilog_state);
				if (var != NOVARIABLE) verilogstate = var->addr; else
					verilogstate = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_verilog_state,
					verilogstate & ~VERILOGUSEASSIGN, VINTEGER);
				ttyputverbose(_("Verilog decks will not use the 'assign' construct"));
				return(0);
			}
			ttyputbadusage("tellaid simulation verilog not");
			return(1);
		}
		ttyputbadusage("tellaid simulation verilog");
		return(1);
	}

	if (namesamen(pp, "fasthenry", l) == 0 && l >= 1)
	{
		l = strlen(pp = par[1]);
		if (namesamen(pp, "pole", l) == 0 && l >= 3)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry pole (single | multiple NUMPOLES)");
				return(1);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "single", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey, options & ~FHMAKEMULTIPOLECKT, VINTEGER);
				return(0);
			}
			if (namesamen(pp, "multiple", l) == 0)
			{
				if (count <= 3)
				{
					ttyputusage("tellaid simulation fasthenry pole multiple NUMPOLES");
					return(1);
				}
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey, options | FHMAKEMULTIPOLECKT, VINTEGER);
				value = atoi(par[3]);
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrynumpoleskey, value, VINTEGER);
				return(0);
			}
			ttyputbadusage("tellaid simulation fasthenry pole");
			return(1);
		}
		if (namesamen(pp, "frequency", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry frequency (single | multiple START END RUNSPERDECADE)");
				return(1);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "single", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				options |= FHUSESINGLEFREQ;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey, options, VINTEGER);
				return(0);
			}
			if (namesamen(pp, "multiple", l) == 0)
			{
				if (count <= 5)
				{
					ttyputusage("tellaid simulation fasthenry frequency multiple START END RUNSPERDECADE");
					return(1);
				}
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				options &= ~FHUSESINGLEFREQ;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey, options, VINTEGER);
				fvalue = (float)atof(par[3]);
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenryfreqstartkey, castint(fvalue), VFLOAT);
				fvalue = (float)atof(par[4]);
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenryfreqendkey, castint(fvalue), VFLOAT);
				value = atoi(par[5]);
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenryrunsperdecadekey, value, VINTEGER);
				return(0);
			}
			ttyputbadusage("tellaid simulation fasthenry frequency");
			return(1);
		}
		if (namesamen(pp, "thickness", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry thickness DEFTHICKNESS");
				return(1);
			}
			value = atola(par[2]);
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrythicknesskey, value, VINTEGER);
			return(0);
		}
		if (namesamen(pp, "width-subdivisions", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry width-subdivisions DEFWIDTHSUBS");
				return(1);
			}
			value = atoi(par[2]);
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrywidthsubdivkey, value, VINTEGER);
			return(0);
		}
		if (namesamen(pp, "height-subdivisions", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry height-subdivisions DEFHEIGHTSUBS");
				return(1);
			}
			value = atoi(par[2]);
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenryheightsubdivkey, value, VINTEGER);
			return(0);
		}
		if (namesamen(pp, "max-segment-length", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry max-segment-length MAXSEGLENGTH");
				return(1);
			}
			value = atola(par[2]);
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenryseglimitkey, value, VINTEGER);
			return(0);
		}
		if (namesamen(pp, "execute", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry execute (none | run | multiple-run)");
				return(1);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "none", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey,
					(options & ~FHEXECUTETYPE) | FHEXECUTENONE, VINTEGER);
				return(0);
			}
			if (namesamen(pp, "run", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey,
					(options & ~FHEXECUTETYPE) | FHEXECUTERUNFH, VINTEGER);
				return(0);
			}
			if (namesamen(pp, "multiple-run", l) == 0)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey,
					(options & ~FHEXECUTETYPE) | FHEXECUTERUNFHMUL, VINTEGER);
				return(0);
			}
			ttyputbadusage("tellaid simulation fasthenry execute");
			return(1);
		}
		if (namesamen(pp, "postscript", l) == 0 && l >= 3)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry postscript (on | off)");
				return(1);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "on", l) == 0 && l >= 2)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey,
					options | FHMAKEPOSTSCRIPTVIEW, VINTEGER);
				return(0);
			}
			if (namesamen(pp, "off", l) == 0 && l >= 2)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey,
					options & ~FHMAKEPOSTSCRIPTVIEW, VINTEGER);
				return(0);
			}
			ttyputbadusage("tellaid simulation fasthenry postscript");
			return(1);
		}
		if (namesamen(pp, "spice", l) == 0)
		{
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry spice (on | off)");
				return(1);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "on", l) == 0 && l >= 2)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey,
					options | FHMAKESPICESUBCKT, VINTEGER);
				return(0);
			}
			if (namesamen(pp, "off", l) == 0 && l >= 2)
			{
				var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_fasthenrystatekey);
				if (var != NOVARIABLE) options = var->addr; else options = 0;
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_fasthenrystatekey,
					options & ~FHMAKESPICESUBCKT, VINTEGER);
				return(0);
			}
			ttyputbadusage("tellaid simulation fasthenry spice");
			return(1);
		}
		if (namesamen(pp, "arc", l) == 0)
		{
			ai = (ARCINST *)askaid(us_aid, "get-arc");
			if (ai == NOARCINST)
			{
				ttyputerr(_("Select an arc first"));
				return(1);
			}
			if (count <= 2)
			{
				ttyputusage("tellaid simulation fasthenry arc OPTIONS");
				return(1);
			}
			l = strlen(pp = par[2]);
			if (namesamen(pp, "add", l) == 0)
			{
				if (count <= 3)
				{
					ttyputusage("tellaid simulation fasthenry arc add GROUPNAME");
					return(1);
				}
				startobjectchange((INTBIG)ai, VARCINST);
				setvalkey((INTBIG)ai, VARCINST, sim_fasthenrygroupnamekey, (INTBIG)par[3], VSTRING|VDISPLAY);
				endobjectchange((INTBIG)ai, VARCINST);
				return(0);
			}
			if (namesamen(pp, "remove", l) == 0)
			{
				if (getvalkey((INTBIG)ai, VARCINST, VSTRING, sim_fasthenrygroupnamekey) != NOVARIABLE)
				{
					startobjectchange((INTBIG)ai, VARCINST);
					delvalkey((INTBIG)ai, VARCINST, sim_fasthenrygroupnamekey);
					endobjectchange((INTBIG)ai, VARCINST);
				}
				return(0);
			}
			if (namesamen(pp, "thickness", l) == 0)
			{
				if (count <= 3)
				{
					if (getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenrythicknesskey) != NOVARIABLE)
					{
						startobjectchange((INTBIG)ai, VARCINST);
						delvalkey((INTBIG)ai, VARCINST, sim_fasthenrythicknesskey);
						endobjectchange((INTBIG)ai, VARCINST);
					}
				} else
				{
					startobjectchange((INTBIG)ai, VARCINST);
					setvalkey((INTBIG)ai, VARCINST, sim_fasthenrythicknesskey, atola(par[3]), VINTEGER);
					endobjectchange((INTBIG)ai, VARCINST);
				}
				return(0);
			}
			if (namesamen(pp, "width-subdivisions", l) == 0)
			{
				if (count <= 3)
				{
					if (getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenrywidthsubdivkey) != NOVARIABLE)
					{
						startobjectchange((INTBIG)ai, VARCINST);
						delvalkey((INTBIG)ai, VARCINST, sim_fasthenrywidthsubdivkey);
						endobjectchange((INTBIG)ai, VARCINST);
					}
				} else
				{
					startobjectchange((INTBIG)ai, VARCINST);
					setvalkey((INTBIG)ai, VARCINST, sim_fasthenrywidthsubdivkey, atoi(par[3]), VINTEGER);
					endobjectchange((INTBIG)ai, VARCINST);
				}
				return(0);
			}
			if (namesamen(pp, "height-subdivisions", l) == 0)
			{
				if (count <= 3)
				{
					if (getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryheightsubdivkey) != NOVARIABLE)
					{
						startobjectchange((INTBIG)ai, VARCINST);
						delvalkey((INTBIG)ai, VARCINST, sim_fasthenryheightsubdivkey);
						endobjectchange((INTBIG)ai, VARCINST);
					}
				} else
				{
					startobjectchange((INTBIG)ai, VARCINST);
					setvalkey((INTBIG)ai, VARCINST, sim_fasthenryheightsubdivkey, atoi(par[3]), VINTEGER);
					endobjectchange((INTBIG)ai, VARCINST);
				}
				return(0);
			}
			if (namesamen(pp, "z-head", l) == 0 && l >= 3)
			{
				if (count <= 3)
				{
					if (getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryzheadkey) != NOVARIABLE)
					{
						startobjectchange((INTBIG)ai, VARCINST);
						delvalkey((INTBIG)ai, VARCINST, sim_fasthenryzheadkey);
						endobjectchange((INTBIG)ai, VARCINST);
					}
				} else
				{
					startobjectchange((INTBIG)ai, VARCINST);
					setvalkey((INTBIG)ai, VARCINST, sim_fasthenryzheadkey, atola(par[3]), VINTEGER);
					endobjectchange((INTBIG)ai, VARCINST);
				}
				return(0);
			}
			if (namesamen(pp, "z-tail", l) == 0 && l >= 3)
			{
				if (count <= 3)
				{
					if (getvalkey((INTBIG)ai, VARCINST, VINTEGER, sim_fasthenryztailkey) != NOVARIABLE)
					{
						startobjectchange((INTBIG)ai, VARCINST);
						delvalkey((INTBIG)ai, VARCINST, sim_fasthenryztailkey);
						endobjectchange((INTBIG)ai, VARCINST);
					}
				} else
				{
					startobjectchange((INTBIG)ai, VARCINST);
					setvalkey((INTBIG)ai, VARCINST, sim_fasthenryztailkey, atola(par[3]), VINTEGER);
					endobjectchange((INTBIG)ai, VARCINST);
				}
				return(0);
			}
			ttyputbadusage("tellaid simulation fasthenry arc");
			return(1);
		}
		ttyputbadusage("tellaid simulation fasthenry");
		return(1);
	}

	/* unknown command */
	ttyputbadusage("tellaid simulation");
	return(1);
}

void sim_slice(void)
{
	NODEPROTO *np;

	if (sim_circuitchanged != 0 && sim_undoredochange == 0)
	{
		if (sim_window_isactive(&np) != 0)
		{
			sim_window_stopsimulation();
			aidturnoff(sim_aid, 0);
			ttyputmsg(_("Circuit changed: simulation stopped"));
			setactivity(_("Simulation Halted"));
		}
	}
	sim_circuitchanged = 0;
	sim_undoredochange = 0;
}

void sim_checktostopsimulation(NODEPROTO *np)
{
	NODEPROTO *onp;

	if (sim_window_isactive(&onp) == 0) return;
	if (onp != np) return;
	sim_circuitchanged = 1;
}

void sim_startbatch(AIDENTRY *source, INTSML undoredo)
{
	sim_undoredochange = undoredo;
}

void sim_modifynodeinst(NODEINST *ni, INTBIG olx, INTBIG oly, INTBIG ohx, INTBIG ohy,
	INTSML orot, INTSML otran)
{
	sim_checktostopsimulation(ni->parent);
}

void sim_modifyarcinst(ARCINST *ai, INTBIG oxA, INTBIG oyA, INTBIG oxB, INTBIG oyB,
	INTBIG owid, INTBIG olen)
{
	sim_checktostopsimulation(ai->parent);
}

void sim_modifyportproto(PORTPROTO *pp, NODEINST *oni, PORTPROTO *opp)
{
	sim_checktostopsimulation(pp->parent);
}

void sim_newobject(INTBIG addr, INTBIG type)
{
	switch (type&VTYPE)
	{
		case VNODEINST:  sim_checktostopsimulation(((NODEINST *)addr)->parent);   break;
		case VARCINST:   sim_checktostopsimulation(((ARCINST *)addr)->parent);    break;
		case VPORTPROTO: sim_checktostopsimulation(((PORTPROTO *)addr)->parent);  break;
	}
}

void sim_killobject(INTBIG addr, INTBIG type)
{
	switch (type&VTYPE)
	{
		case VNODEINST:  sim_checktostopsimulation(((NODEINST *)addr)->parent);   break;
		case VARCINST:   sim_checktostopsimulation(((ARCINST *)addr)->parent);    break;
		case VPORTPROTO: sim_checktostopsimulation(((PORTPROTO *)addr)->parent);  break;
	}
}

void sim_newvariable(INTBIG addr, INTBIG type, INTBIG key, INTBIG newtype)
{
	REGISTER char *name;
	ARCINST *ai;

	/* detect change to "ai->userbits" to see if arc negation changed */
	if ((newtype&VCREF) == 0) return;
	if ((type&VTYPE) != VARCINST) return;
	name = changedvariablename(type, key, newtype);
	if (namesame(name, "userbits") != 0) return;

	ai = (ARCINST *)addr;
	if (ai != sim_modifyarc) return;
	if (((INTBIG)(ai->userbits&ISNEGATED)) != (sim_modifyarcbits&ISNEGATED))
		sim_checktostopsimulation(ai->parent);
}

void sim_killvariable(INTBIG addr, INTBIG type, INTBIG key, INTBIG oldaddr, INTBIG oldtype,
	INTBIG olddescript)
{
	REGISTER char *name;

	/* detect change to "ai->userbits" and save former value */
	if ((oldtype&VCREF) == 0) return;
	if ((type&VTYPE) != VARCINST) return;
	name = changedvariablename(type, key, oldtype);
	if (namesame(name, "userbits") != 0) return;

	sim_modifyarc = (ARCINST *)addr;
	sim_modifyarcbits = sim_modifyarc->userbits;
}

/****************************** DIALOG ******************************/

/*
 * special case for the "Simulation Options" dialog
 * Resimulate each change = 3 (check)
 * Auto advance time      = 4 (check)
 * Multistate display     = 5 (check)
 * Show waveform window   = 6 (check)
 * Maximum events         = 8 (edit text)
 */
void sim_optionsdlog(void)
{
	INTBIG itemHit, newtracesize;
	REGISTER VARIABLE *var;
	char line[20];
	REGISTER INTBIG noupdate, windowstate, newnoupdate, newwindowstate;
	REGISTER TRAKPTR newtrakroot;

	if (DiaInitDialog(&sim_optionsdialog) != 0) return;
	var = getval((INTBIG)sim_aid, VAID, VINTEGER, "SIM_als_no_update");
	if (var == NOVARIABLE) noupdate = 0; else noupdate = var->addr;
	var = getval((INTBIG)sim_aid, VAID, VINTEGER, "SIM_window_state");
	if (var == NOVARIABLE) windowstate = 0; else windowstate = var->addr;
	if (noupdate == 0) DiaSetControl(3, 1);
	if ((windowstate&ADVANCETIME) != 0) DiaSetControl(4, 1);
	if ((windowstate&FULLSTATE) != 0) DiaSetControl(5, 1);
	if ((windowstate&SHOWWAVEFORM) != 0) DiaSetControl(6, 1);
	if (simals_trace_size == 0)
	{
		var = getval((INTBIG)sim_aid, VAID, VINTEGER, "SIM_als_num_events");
		if (var == NOVARIABLE) simals_trace_size = DEFAULT_TRACE_SIZE; else
			simals_trace_size = var->addr;
	}
	sprintf(line, "%ld", simals_trace_size);
	DiaSetText(8, line);

	/* loop until done */
	for(;;)
	{
		itemHit = DiaNextHit();
		if (itemHit == OK || itemHit == CANCEL) break;
		if (itemHit >= 3 && itemHit <= 6)
		{
			DiaSetControl(itemHit, 1 - DiaGetControl(itemHit));
			continue;
		}
	}

	if (itemHit != CANCEL)
	{
		if (DiaGetControl(3) != 0) newnoupdate = 0; else
			newnoupdate = 1;
		newwindowstate = 0;
		if (DiaGetControl(4) != 0) newwindowstate |= ADVANCETIME;
		if (DiaGetControl(5) != 0) newwindowstate |= FULLSTATE;
		if (DiaGetControl(6) != 0) newwindowstate |= SHOWWAVEFORM;
		if (newnoupdate != noupdate)
			(void)setval((INTBIG)sim_aid, VAID, "SIM_als_no_update",
				newnoupdate, VINTEGER);
		if (newwindowstate != windowstate)
			(void)setval((INTBIG)sim_aid, VAID, "SIM_window_state",
				newwindowstate, VINTEGER);
		newtracesize = atoi(DiaGetText(8));
		if (newtracesize != simals_trace_size)
		{
			newtrakroot = (TRAKPTR)simals_alloc_mem((INTBIG)(newtracesize * sizeof(TRAK)));
			if (newtrakroot != 0)
			{
				if (simals_trakroot != 0) efree((char *)simals_trakroot);
				simals_trakroot = newtrakroot;
				simals_trace_size = newtracesize;
				(void)setval((INTBIG)sim_aid, VAID, "SIM_als_num_events",
					newtracesize, VINTEGER);
			}
		}
	}
	DiaDoneDialog();
}

/*
 * special case for the "als clock" dialog
 */
#define	MAXPHASES 20
INTSML sim_alsclockdlog(char *paramstart[])
{
	INTBIG itemHit, i, j;
	INTSML retval;
	char *line;
	float durval[MAXPHASES];
	INTBIG levval[MAXPHASES], phases;
	static char *retdur[MAXPHASES];
	static INTBIG first = 0;

	/* display the ALS clock dialog box */
	if (DiaInitDialog(&sim_alsclockdialog) != 0) return(0);
	DiaInitTextDialog(16, DiaNullDlogList, DiaNullDlogItem, DiaNullDlogDone, -1, 0);

	/* setup complex clock specification */
	DiaSetText(11, "0.0");	/* random */
	DiaSetControl(8, 1);	/* gate strength */
	DiaSetControl(14, 1);	/* level */
	DiaSetText(20, "0");	/* infinite cycles */

	/* now disable complex clock specification */
	DiaSetControl(3, 1);										/* frequency */
	DiaDimItem(10);   DiaDimItem(11);   DiaNoEditControl(11);	/* random */
	DiaDimItem(13);   DiaDimItem(8);    DiaDimItem(12);			/* strength */
	DiaDimItem(23);   DiaDimItem(14);   DiaDimItem(9);			/* level */
	DiaDimItem(17);   DiaDimItem(21);   DiaNoEditControl(21);	/* duration */
	DiaDimItem(18);   DiaDimItem(15);							/* add/delete */
	DiaDimItem(22);												/* list header */
	DiaDimItem(19);   DiaDimItem(20);   DiaNoEditControl(20);	/* cycles */
	DiaUnDimItem(7);  DiaUnDimItem(6);  DiaEditControl(6);		/* freq/per */

	/* loop until done */
	phases = 0;
	for(;;)
	{
		itemHit = DiaNextHit();
		if (itemHit == OK || itemHit == CANCEL) break;
		if (itemHit == 3 || itemHit == 4 || itemHit == 5)
		{
			DiaSetControl(3, 0);   DiaSetControl(4, 0);   DiaSetControl(5, 0);
			DiaSetControl(itemHit, 1);
			if (itemHit == 5)
			{
				DiaUnDimItem(10);   DiaUnDimItem(11);   DiaEditControl(11);	/* random */
				DiaUnDimItem(13);   DiaUnDimItem(8);    DiaUnDimItem(12);	/* strength */
				DiaUnDimItem(23);   DiaUnDimItem(14);   DiaUnDimItem(9);	/* level */
				DiaUnDimItem(17);   DiaUnDimItem(21);   DiaEditControl(21);	/* duration */
				DiaUnDimItem(18);   DiaUnDimItem(15);						/* add/delete */
				DiaUnDimItem(22);											/* list header */
				DiaUnDimItem(19);   DiaUnDimItem(20);   DiaEditControl(20);	/* cycles */
				DiaDimItem(7);      DiaDimItem(6);      DiaNoEditControl(6);/* freq/per */
			} else
			{
				DiaDimItem(10);   DiaDimItem(11);   DiaNoEditControl(11);	/* random */
				DiaDimItem(13);   DiaDimItem(8);    DiaDimItem(12);			/* strength */
				DiaDimItem(23);   DiaDimItem(14);   DiaDimItem(9);			/* level */
				DiaDimItem(17);   DiaDimItem(21);   DiaNoEditControl(21);	/* duration */
				DiaDimItem(18);   DiaDimItem(15);							/* add/delete */
				DiaDimItem(22);												/* list header */
				DiaDimItem(19);   DiaDimItem(20);   DiaNoEditControl(20);	/* cycles */
				DiaUnDimItem(7);  DiaUnDimItem(6);  DiaEditControl(6);		/* freq/per */
			}
			continue;
		}
		if (itemHit == 13 || itemHit == 8 || itemHit == 12)
		{
			DiaSetControl(13, 0);   DiaSetControl(8, 0);   DiaSetControl(12, 0);
			DiaSetControl(itemHit, 1);
			continue;
		}
		if (itemHit == 23 || itemHit == 14 || itemHit == 9)
		{
			DiaSetControl(23, 0);   DiaSetControl(14, 0);   DiaSetControl(9, 0);
			DiaSetControl(itemHit, 1);
			continue;
		}
		if (itemHit == 18)
		{
			/* add phase */
			if (phases >= MAXPHASES) continue;
			line = DiaGetText(21);
			durval[phases] = (float)atof(line);
			if (DiaGetControl(23) != 0) levval[phases] = 0; else
				if (DiaGetControl(14) != 0) levval[phases] = 1; else levval[phases] = 2;
			phases++;
			sim_writephases(durval, levval, phases);
			continue;
		}
		if (itemHit == 15)
		{
			/* delete phase */
			if (phases <= 0) continue;
			j = DiaGetCurLine(16);
			for(i=j; i<phases; i++)
			{
				durval[i] = durval[i+1];
				levval[i] = levval[i+1];
			}
			phases--;
			sim_writephases(durval, levval, phases);
			continue;
		}
	}
	retval = 0;
	if (itemHit == OK && DiaGetControl(3) != 0)
	{
		paramstart[0] = "frequency";
		paramstart[1] = us_putintoinfstr(DiaGetText(6));
		retval = 2;
	} else if (itemHit == OK && DiaGetControl(4) != 0)
	{
		paramstart[0] = "period";
		paramstart[1] = us_putintoinfstr(DiaGetText(6));
		retval = 2;
	} else if (itemHit == OK && DiaGetControl(5) != 0)
	{
		paramstart[0] = "custom";
		paramstart[1] = us_putintoinfstr(DiaGetText(11));
		if (DiaGetControl(13) != 0) paramstart[2] = "1"; else
			if (DiaGetControl(8) != 0) paramstart[2] = "2"; else
				paramstart[2] = "3";
		paramstart[3] = us_putintoinfstr(DiaGetText(20));
		retval = 4;
		if (first == 0) for(i=0; i<MAXPHASES; i++) retdur[i] = 0;
		first++;
		for(i=0; i<phases; i++)
		{
			if (retdur[i] != 0) efree(retdur[i]);
			retdur[i] = (char *)emalloc(50, sim_aid->cluster);
			if (retdur[i] == 0) break;
			(void)sprintf(retdur[i], "%e", durval[i]);
			paramstart[retval++] = (levval[i]==0 ? "low" : (levval[i]==1 ? "high" : "undefined"));
			paramstart[retval++] = retdur[i];
		}
	}
	DiaDoneDialog();
	return(retval);
}

void sim_writephases(float durval[], INTBIG levval[], INTBIG phases)
{
	INTBIG i;
	char lne[50];

	DiaLoadTextDialog(16, DiaNullDlogList, DiaNullDlogItem, DiaNullDlogDone, -1);
	for(i=0; i<phases; i++)
	{
		(void)sprintf(lne, _("%s for %e"),
			(levval[i]==0 ? _("low") : (levval[i]==1 ? _("high") : _("undefined"))), durval[i]);
		DiaStuffLine(16, lne);
	}
	if (phases <= 0) DiaSelectLine(16, -1); else DiaSelectLine(16, 0);
}

/*
 * special case for the "SPICE options" dialog
 * Layer list             = 28 (scroll)
 * Layer resistance       = 33 (edit text)
 * Layer capacitance      = 34 (edit text)
 * Layer edge capacitance = 35 (edit text)
 * Minimum resistance     = 37 (edit text)
 * Minimum capacitance    = 39 (edit text)
 */
void sim_spicedlog(void)
{
	INTBIG itemHit, i, level, execute, canexecute, reschanged,
		capchanged, ecapchanged;
	REGISTER INTBIG j, l, spice_state, newspice_state;
	INTSML oldplease, dummy;
	char *subparams[3], *pt, header[200], *dummyfile[1], floatconv[30], *newlang[5];
	static char *formatnames[3] = {N_("Spice 2"), N_("Spice 3"), N_("Hspice")};
	static char *levelnames[3] = {"1", "2", "3"};
	static char *executenames[5] = {N_("Don't Run SPICE"), N_("Run SPICE"), N_("Run SPICE Quietly"),
		N_("Run SPICE, Read Output"), N_("Run SPICE Quietly, Read Output")};
	static char qual[50];
	float *res, *cap, *ecap, minres, mincap, v;
	REGISTER VARIABLE *var, *varres, *varcap, *varecap;
	REGISTER NODEPROTO *np;
	REGISTER WINDOWPART *w;
	REGISTER EDITOR *ed;
	extern COMCOMP us_colorreadp;

	/* Display the SPICE options dialog box */
	if (DiaInitDialog(&sim_spiceoptdialog) != 0) return;
	for(i=0; i<5; i++) newlang[i] = _(executenames[i]); DiaSetPopup(3, 5, newlang);
	for(i=0; i<3; i++) newlang[i] = _(formatnames[i]);  DiaSetPopup(4, 3, newlang);
	for(i=0; i<3; i++) newlang[i] = _(levelnames[i]);   DiaSetPopup(7, 3, newlang);

	/* state of the execute flag */
	canexecute = graphicshas(CANRUNPROCESS);
	if (canexecute != 0)
	{
		var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_dontrun);
		if (var == NOVARIABLE) execute = 3; else
		{
			switch (var->addr)
			{
				case SIMRUNNO:        execute = 0;   break;
				case SIMRUNYES:       execute = 1;   break;
				case SIMRUNYESQ:      execute = 2;   break;
				case SIMRUNYESPARSE:  execute = 3;   break;
				case SIMRUNYESQPARSE: execute = 4;   break;
			}
		}
		DiaSetPopupEntry(3, execute);
	} else
	{
		DiaDimItem(3);
	}

	/* get the spice level */
	var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_level);
	if (var == NOVARIABLE) level = 1; else level = var->addr;
	DiaSetPopupEntry(7, level-1);

	/* get miscellaneous state */
	var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_spice_state);
	if (var != NOVARIABLE) spice_state = var->addr; else spice_state = 0;
	if ((spice_state&SPICENODENAMES) != 0) DiaSetControl(10, 1);
	if ((spice_state&SPICERESISTANCE) != 0) DiaSetControl(11, 1);
	switch (spice_state & SPICETYPE)
	{
		case SPICE2:      DiaSetPopupEntry(4, 0);   DiaDimItem(10);     break;
		case SPICE3:      DiaSetPopupEntry(4, 1);   DiaUnDimItem(10);   break;
		case SPICEHSPICE: DiaSetPopupEntry(4, 2);   DiaUnDimItem(10);   break;
	}

	/* get model and trailer cards */
	(void)initinfstr();
	(void)formatinfstr(_("For technology: %s"), el_curtech->techname);
	DiaSetText(20, returninfstr());
	var = getval((INTBIG)el_curtech, VTECHNOLOGY, VSTRING, "SIM_spice_model_file");
	if (var != NOVARIABLE)
	{
		DiaSetText(16, (char *)var->addr);
		DiaSetControl(15, 1);
		DiaUnDimItem(21);
	} else
	{
		DiaSetControl(14, 1);
		DiaDimItem(21);
	}
	var = getval((INTBIG)el_curtech, VTECHNOLOGY, VSTRING, "SIM_spice_trailer_file");
	if (var != NOVARIABLE)
	{
		DiaSetText(19, (char *)var->addr);
		DiaSetControl(18, 1);
		DiaUnDimItem(22);
	} else
	{
		DiaSetControl(17, 1);
		DiaDimItem(22);
	}

	/* list of facets for model description files */
	DiaInitTextDialog(23, topoffacets, nextfacets, DiaNullDlogDone,
		0, SCSELMOUSE|SCSELKEY|SCREPORT);
	for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
	{
		np->temp1 = 0;
		var = getval((INTBIG)np, VNODEPROTO, VSTRING, "SIM_spice_behave_file");
		if (var != NOVARIABLE)
			(void)allocstring((char **)&np->temp1, (char *)var->addr, el_tempcluster);
	}
	pt = DiaGetScrollLine(23, DiaGetCurLine(23));
	DiaSetControl(6, 1);   DiaSetControl(5, 0);
	DiaSetText(9, "");     DiaDimItem(8);
	np = getnodeproto(pt);
	if (np != NONODEPROTO)
	{
		var = getval((INTBIG)np, VNODEPROTO, VSTRING, "SIM_spice_behave_file");
		if (var != NOVARIABLE)
		{
			DiaSetControl(6, 0);   DiaSetControl(5, 1);
			DiaSetText(9, (char *)var->addr);   DiaUnDimItem(8);
		}
	}

	/* list of layers in this technology, with resistance, capacitance, etc. */
	DiaInitTextDialog(28, DiaNullDlogList, DiaNullDlogItem, DiaNullDlogDone,
		-1, SCSELMOUSE|SCREPORT);
	varres = getval((INTBIG)el_curtech, VTECHNOLOGY, VFLOAT|VISARRAY, "SIM_spice_resistance");
	varcap = getval((INTBIG)el_curtech, VTECHNOLOGY, VFLOAT|VISARRAY, "SIM_spice_capacitance");
	varecap = getval((INTBIG)el_curtech, VTECHNOLOGY, VFLOAT|VISARRAY, "SIM_spice_edge_capacitance");
	res = (float *)emalloc(el_curtech->layercount * (sizeof (float)), el_tempcluster);
	cap = (float *)emalloc(el_curtech->layercount * (sizeof (float)), el_tempcluster);
	ecap = (float *)emalloc(el_curtech->layercount * (sizeof (float)), el_tempcluster);
	for(i=0; i<el_curtech->layercount; i++)
	{
		DiaStuffLine(28, layername(el_curtech, (INTSML)i));
		res[i] = cap[i] = ecap[i] = 0.0;
		if (varres != NOVARIABLE && i < getlength(varres))
			res[i] = ((float *)varres->addr)[i];
		if (varcap != NOVARIABLE && i < getlength(varcap))
			cap[i] = ((float *)varcap->addr)[i];
		if (varecap != NOVARIABLE && i < getlength(varecap))
			ecap[i] = ((float *)varecap->addr)[i];
	}
	DiaSelectLine(28, 0);
	sprintf(floatconv, "%g", res[0]);    DiaSetText(33, floatconv);
	sprintf(floatconv, "%g", cap[0]);    DiaSetText(34, floatconv);
	sprintf(floatconv, "%g", ecap[0]);   DiaSetText(35, floatconv);
	reschanged = capchanged = ecapchanged = 0;

	/* get minimum resistance and capacitances */
	var = getval((INTBIG)el_curtech, VTECHNOLOGY, VFLOAT, "SIM_spice_min_resistance");
	if (var == NOVARIABLE) minres = 0.0; else
		minres = castfloat(var->addr);
	sprintf(floatconv, "%g", minres);    DiaSetText(37, floatconv);
	var = getval((INTBIG)el_curtech, VTECHNOLOGY, VFLOAT, "SIM_spice_min_capacitance");
	if (var == NOVARIABLE) mincap = 0.0; else
		mincap = castfloat(var->addr);
	sprintf(floatconv, "%g", mincap);    DiaSetText(39, floatconv);

	for(;;)
	{
		itemHit = DiaNextHit();
		if (itemHit == OK || itemHit == CANCEL || itemHit == 25) break;

		if (itemHit == 4)
		{
			/* file format button */
			if (DiaGetPopupEntry(4) != 0) DiaUnDimItem(10); else DiaDimItem(10);
			continue;
		}

		if (itemHit == 10 || itemHit == 11)
		{
			/* check boxes */
			DiaSetControl(itemHit, 1-DiaGetControl(itemHit));
			continue;
		}

		if (itemHit == 14 || itemHit == 15)
		{
			/* model cards button */
			DiaSetControl(14, 0);   DiaSetControl(15, 0);
			DiaSetControl(itemHit, 1);
			if (itemHit == 15)
			{
				DiaUnDimItem(21);   DiaUnDimItem(16);
				itemHit = 21;
			} else
			{
				DiaDimItem(21);   DiaDimItem(16);
				continue;
			}
		}
		if (itemHit == 21)
		{
			/* select model cards */
			oldplease = el_pleasestop;
			(void)initinfstr();
			(void)addstringtoinfstr("spice/");
			(void)addstringtoinfstr(_("SPICE Model File"));
			i = ttygetparam(returninfstr(), &us_colorreadp, 1, subparams);
			el_pleasestop = oldplease;
			if (i != 0 && subparams[0][0] != 0) DiaSetText(16, subparams[0]);
			if (*DiaGetText(16) == 0)
			{
				DiaSetControl(14, 1);   DiaSetControl(15, 0);
				DiaDimItem(21);         DiaDimItem(16);
			}
			continue;
		}

		if (itemHit == 17 || itemHit == 18)
		{
			/* trailer cards button */
			DiaSetControl(17, 0);   DiaSetControl(18, 0);
			DiaSetControl(itemHit, 1);
			if (itemHit == 18)
			{
				DiaUnDimItem(22);   DiaUnDimItem(19);
				itemHit = 22;
			} else
			{
				DiaDimItem(22);   DiaDimItem(19);
				continue;
			}
		}

		if (itemHit == 22)
		{
			/* select trailer cards */
			oldplease = el_pleasestop;
			(void)initinfstr();
			(void)addstringtoinfstr("spice/");
			(void)addstringtoinfstr(_("SPICE Trailer File"));
			i = ttygetparam(returninfstr(), &us_colorreadp, 1, subparams);
			el_pleasestop = oldplease;
			if (i != 0 && subparams[0][0] != 0) DiaSetText(19, subparams[0]);
			if (*DiaGetText(19) == 0)
			{
				DiaSetControl(17, 1);   DiaSetControl(18, 0);
				DiaDimItem(22);         DiaDimItem(19);
			}
			continue;
		}

		if (itemHit == 23)
		{
			/* selection of facets */
			DiaSetControl(6, 1);   DiaSetControl(5, 0);
			DiaSetText(9, "");     DiaDimItem(8);
			pt = DiaGetScrollLine(23, DiaGetCurLine(23));
			np = getnodeproto(pt);
			if (np != NONODEPROTO && np->temp1 != 0)
			{
				DiaSetControl(6, 0);   DiaSetControl(5, 1);
				DiaSetText(9, (char *)np->temp1);   DiaUnDimItem(8);
			}
			continue;
		}

		if (itemHit == 28)
		{
			/* selection of layers */
			i = DiaGetCurLine(28);
			if (i < 0 || i >= el_curtech->layercount) continue;
			sprintf(floatconv, "%g", res[i]);   DiaSetText(33, floatconv);
			sprintf(floatconv, "%g", cap[i]);   DiaSetText(34, floatconv);
			sprintf(floatconv, "%g", ecap[i]);   DiaSetText(35, floatconv);
			continue;
		}
		if (itemHit == 33)
		{
			i = DiaGetCurLine(28);
			if (i < 0 || i >= el_curtech->layercount) continue;
			v = (float)atof(DiaGetText(33));
			if (res[i] != v) reschanged++;
			res[i] = v;
			continue;
		}
		if (itemHit == 34)
		{
			i = DiaGetCurLine(28);
			if (i < 0 || i >= el_curtech->layercount) continue;
			v = (float)atof(DiaGetText(34));
			if (cap[i] != v) capchanged++;
			cap[i] = v;
			continue;
		}
		if (itemHit == 35)
		{
			i = DiaGetCurLine(28);
			if (i < 0 || i >= el_curtech->layercount) continue;
			v = (float)atof(DiaGetText(35));
			if (ecap[i] != v) ecapchanged++;
			ecap[i] = v;
			continue;
		}

		if (itemHit == 6 || itemHit == 5)
		{
			/* model for facet */
			DiaSetControl(6, 0);   DiaSetControl(5, 0);
			DiaSetControl(itemHit, 1);
			if (itemHit == 5)
			{
				DiaUnDimItem(8);   DiaUnDimItem(9);
				itemHit = 8;
			} else
			{
				DiaDimItem(8);   DiaDimItem(9);
				DiaSetText(9, "");
				pt = DiaGetScrollLine(23, DiaGetCurLine(23));
				np = getnodeproto(pt);
				if (np != NONODEPROTO)
				{
					if (np->temp1 != 0) efree((char *)np->temp1);
					np->temp1 = 0;
				}
				continue;
			}
		}

		if (itemHit == 8)
		{
			/* set model for facet */
			pt = DiaGetScrollLine(23, DiaGetCurLine(23));
			np = getnodeproto(pt);
			if (np == NONODEPROTO) continue;
			oldplease = el_pleasestop;
			(void)initinfstr();
			(void)addstringtoinfstr("spice/");
			(void)addstringtoinfstr(_("Facet's Model File"));
			i = ttygetparam(returninfstr(), &us_colorreadp, 1, subparams);
			el_pleasestop = oldplease;
			if (i != 0 && subparams[0][0] != 0)
			{
				DiaSetText(9, subparams[0]);
				if (np->temp1 != 0) efree((char *)np->temp1);
				(void)allocstring((char **)&np->temp1, subparams[0], el_tempcluster);
			} else
			{
				DiaSetControl(6, 1);   DiaSetControl(5, 0);
				DiaDimItem(8);         DiaDimItem(9);
			}
			continue;
		}
	}

	if (itemHit != CANCEL)  /* now update the values */
	{
		if (canexecute != 0)
		{
			i = DiaGetPopupEntry(3);
			if (i != execute)
			{
				switch (i)
				{
					case 0: execute = SIMRUNNO;          break;
					case 1: execute = SIMRUNYES;         break;
					case 2: execute = SIMRUNYESQ;        break;
					case 3: execute = SIMRUNYESPARSE;    break;
					case 4: execute = SIMRUNYESQPARSE;   break;
				}
				(void)setvalkey((INTBIG)sim_aid, VAID, sim_dontrun, execute, VINTEGER);
			}
		}

		i = DiaGetPopupEntry(7) + 1;
		if (i != level)
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_level, i, VINTEGER);

		newspice_state = 0;
		if (DiaGetControl(10) != 0) newspice_state |= SPICENODENAMES;
		if (DiaGetControl(11) != 0) newspice_state |= SPICERESISTANCE;
		switch (DiaGetPopupEntry(4))
		{
			case 0: newspice_state |= SPICE2;        break;
			case 1: newspice_state |= SPICE3;        break;
			case 2: newspice_state |= SPICEHSPICE;   break;
		}
		if (newspice_state != spice_state)
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_spice_state, newspice_state, VINTEGER);

		var = getval((INTBIG)el_curtech, VTECHNOLOGY, VSTRING, "SIM_spice_model_file");
		if (DiaGetControl(15) != 0)
		{
			/* set model cards */
			pt = DiaGetText(16);
			if (var == NOVARIABLE || strcmp(pt, (char *)var->addr) != 0)
			{
				(void)setval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_model_file",
					(INTBIG)pt, VSTRING);
			}
		} else
		{
			/* remove model cards */
			if (var != NOVARIABLE)
				(void)delval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_model_file");
		}

		var = getval((INTBIG)el_curtech, VTECHNOLOGY, VSTRING, "SIM_spice_trailer_file");
		if (DiaGetControl(18) != 0)
		{
			/* set trailer cards */
			pt = DiaGetText(19);
			if (var == NOVARIABLE || strcmp(pt, (char *)var->addr) != 0)
			{
				(void)setval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_trailer_file",
					(INTBIG)pt, VSTRING);
			}
		} else
		{
			/* remove trailer cards */
			if (var != NOVARIABLE)
				(void)delval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_trailer_file");
		}
		for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
		{
			var = getval((INTBIG)np, VNODEPROTO, VSTRING, "SIM_spice_behave_file");
			if (var != NOVARIABLE)
			{
				if (np->temp1 == 0)
					(void)delval((INTBIG)np, VNODEPROTO, "SIM_spice_behave_file"); else
				{
					if (strcmp((char *)np->temp1, (char *)var->addr) != 0)
						(void)setval((INTBIG)np, VNODEPROTO, "SIM_spice_behave_file", (INTBIG)np->temp1, VSTRING);
				}
			} else if (np->temp1 != 0)
				(void)setval((INTBIG)np, VNODEPROTO, "SIM_spice_behave_file", (INTBIG)np->temp1, VSTRING);
			if (np->temp1 != 0) efree((char *)np->temp1);
		}

		/* update layer resistance, capacitance, etc. */
		if (reschanged != 0)
			setval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_resistance",
				(INTBIG)res, VFLOAT|VISARRAY|(el_curtech->layercount << VLENGTHSH));
		if (capchanged != 0)
			setval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_capacitance",
				(INTBIG)cap, VFLOAT|VISARRAY|(el_curtech->layercount << VLENGTHSH));
		if (ecapchanged != 0)
			setval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_edge_capacitance",
				(INTBIG)ecap, VFLOAT|VISARRAY|(el_curtech->layercount << VLENGTHSH));

		/* update minimum resistance and capacitance */
		v = (float)atof(DiaGetText(37));
		if (v != minres)
			setval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_min_resistance",
				castint(v), VFLOAT);
		v = (float)atof(DiaGetText(39));
		if (v != mincap)
			setval((INTBIG)el_curtech, VTECHNOLOGY, "SIM_spice_min_capacitance",
				castint(v), VFLOAT);
	}
	DiaDoneDialog();
	efree((char *)res);
	efree((char *)cap);
	efree((char *)ecap);
	if (itemHit == 25)
	{
		/* now edit the model cards */
		sprintf(qual, "SIM_spice_header_level%d", level);
		sprintf(header, _("Level %d SPICE Model cards for %s"), level, el_curtech->techname);

		var = getval((INTBIG)el_curtech, VTECHNOLOGY, -1, qual);
		if (var == NOVARIABLE)
		{
			dummyfile[0] = "";
			var = setval((INTBIG)el_curtech, VTECHNOLOGY, qual, (INTBIG)dummyfile,
				VSTRING|VISARRAY|(1<<VLENGTHSH));
			if (var == NOVARIABLE)
			{
				ttyputerr(_("Cannot create %s on the technology"), qual);
				return;
			}
		} else
			var->type &= ~VDONTSAVE;

		/* get a new window, put an editor in it */
		w = us_wantnewwindow(0);
		if (w == NOWINDOWPART) return;
		if (us_makeeditor(w, header, &dummy, &dummy) == NOWINDOWPART) return;
		ed = w->editor;
		ed->editobjqual = qual;
		ed->editobjaddr = (char *)el_curtech;
		ed->editobjtype = VTECHNOLOGY;
		ed->editobjvar = var;
		us_suspendgraphics(w);

		l = getlength(var);
		for(j=0; j<l; j++)
		{
			(void)initinfstr();
			(void)addstringtoinfstr(describevariable(var, (INTSML)j, -1));
			us_addline(w, j, returninfstr());
		}
		us_resumegraphics(w);
		w->changehandler = us_varchanges;
	}
}

/*
 * special case for the "Verilog options" dialog
 */
void sim_verilogdlog(void)
{
	INTBIG itemHit, i, verilog_state;
	INTSML oldplease;
	char *subparams[3], *pt;
	REGISTER VARIABLE *var;
	REGISTER NODEPROTO *np;
	extern COMCOMP us_colorreadp;

	/* Display the Verilog options dialog box */
	if (DiaInitDialog(&sim_verilogoptdialog) != 0) return;

	/* get miscellaneous state */
	var = getvalkey((INTBIG)sim_aid, VAID, VINTEGER, sim_verilog_state);
	if (var != NOVARIABLE) verilog_state = var->addr; else verilog_state = 0;
	if ((verilog_state&VERILOGUSEASSIGN) != 0) DiaSetControl(7, 1);

	/* list of facets for model description files */
	DiaInitTextDialog(8, topoffacets, nextfacets, DiaNullDlogDone,
		0, SCSELMOUSE|SCSELKEY|SCREPORT);
	for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
	{
		np->temp1 = 0;
		var = getval((INTBIG)np, VNODEPROTO, VSTRING, "SIM_verilog_behave_file");
		if (var != NOVARIABLE)
			(void)allocstring((char **)&np->temp1, (char *)var->addr, el_tempcluster);
	}
	pt = DiaGetScrollLine(8, DiaGetCurLine(8));
	DiaSetControl(4, 1);   DiaSetControl(3, 0);
	DiaSetText(6, "");     DiaDimItem(5);
	np = getnodeproto(pt);
	if (np != NONODEPROTO)
	{
		var = getval((INTBIG)np, VNODEPROTO, VSTRING, "SIM_verilog_behave_file");
		if (var != NOVARIABLE)
		{
			DiaSetControl(4, 0);   DiaSetControl(3, 1);
			DiaSetText(6, (char *)var->addr);   DiaUnDimItem(5);
		}
	}

	for(;;)
	{
		itemHit = DiaNextHit();
		if (itemHit == OK || itemHit == CANCEL) break;

		if (itemHit == 7)
		{
			/* use ASSIGN statement */
			DiaSetControl(itemHit, 1-DiaGetControl(itemHit));
			continue;
		}

		if (itemHit == 8)
		{
			/* selection of facets */
			DiaSetControl(4, 1);   DiaSetControl(3, 0);
			DiaSetText(6, "");     DiaDimItem(5);
			pt = DiaGetScrollLine(8, DiaGetCurLine(8));
			np = getnodeproto(pt);
			if (np != NONODEPROTO && np->temp1 != 0)
			{
				DiaSetControl(4, 0);   DiaSetControl(3, 1);
				DiaSetText(6, (char *)np->temp1);   DiaUnDimItem(5);
			}
			continue;
		}

		if (itemHit == 3 || itemHit == 4)
		{
			/* model for facet */
			DiaSetControl(3, 0);   DiaSetControl(4, 0);
			DiaSetControl(itemHit, 1);
			if (itemHit == 3)
			{
				DiaUnDimItem(5);   DiaUnDimItem(6);
				itemHit = 5;
			} else
			{
				DiaDimItem(5);   DiaDimItem(6);
				DiaSetText(6, "");
				pt = DiaGetScrollLine(8, DiaGetCurLine(8));
				np = getnodeproto(pt);
				if (np != NONODEPROTO)
				{
					if (np->temp1 != 0) efree((char *)np->temp1);
					np->temp1 = 0;
				}
				continue;
			}
		}

		if (itemHit == 5)
		{
			/* set model for facet */
			pt = DiaGetScrollLine(8, DiaGetCurLine(8));
			np = getnodeproto(pt);
			if (np == NONODEPROTO) continue;
			oldplease = el_pleasestop;
			(void)initinfstr();
			(void)addstringtoinfstr("verilog/");
			(void)addstringtoinfstr(_("Facet's Model File"));
			i = ttygetparam(returninfstr(), &us_colorreadp, 1, subparams);
			el_pleasestop = oldplease;
			if (i != 0 && subparams[0][0] != 0)
			{
				DiaSetText(6, subparams[0]);
				if (np->temp1 != 0) efree((char *)np->temp1);
				(void)allocstring((char **)&np->temp1, subparams[0], el_tempcluster);
			} else
			{
				DiaSetControl(4, 1);   DiaSetControl(3, 0);
				DiaDimItem(5);         DiaDimItem(6);
			}
			continue;
		}
	}

	if (itemHit != CANCEL)  /* now update the values */
	{
		i = 0;
		if (DiaGetControl(7) != 0) i |= VERILOGUSEASSIGN;
		if (i != verilog_state)
			(void)setvalkey((INTBIG)sim_aid, VAID, sim_verilog_state, i, VINTEGER);

		for(np = el_curlib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
		{
			var = getval((INTBIG)np, VNODEPROTO, VSTRING, "SIM_verilog_behave_file");
			if (var != NOVARIABLE)
			{
				if (np->temp1 == 0)
					(void)delval((INTBIG)np, VNODEPROTO, "SIM_verilog_behave_file"); else
				{
					if (strcmp((char *)np->temp1, (char *)var->addr) != 0)
						(void)setval((INTBIG)np, VNODEPROTO, "SIM_verilog_behave_file",
							(INTBIG)np->temp1, VSTRING);
				}
			} else if (np->temp1 != 0)
				(void)setval((INTBIG)np, VNODEPROTO, "SIM_verilog_behave_file",
					(INTBIG)np->temp1, VSTRING);
			if (np->temp1 != 0) efree((char *)np->temp1);
		}
	}
	DiaDoneDialog();
}

#endif  /* SIMAID */
