home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-28 | 61.2 KB | 2,113 lines |
- Path: sparky!uunet!crdgw1!rpi!usc!howland.reston.ans.net!bogus.sura.net!darwin.sura.net!ukma!cs.widener.edu!dsinc!ub!galileo.cc.rochester.edu!ee.rochester.edu!rbc!al
- From: al@rbc.uucp (Al Davis)
- Newsgroups: alt.sources
- Subject: ACS circuit simulator part 18/20
- Message-ID: <1993Jan27.041057.12044@rbc.uucp>
- Date: 27 Jan 93 04:10:57 GMT
- Sender: al@rbc.uucp (Al Davis)
- Organization: Huh?
- Lines: 2102
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # src/tr_clear.c
- # src/tr_conck.c
- # src/tr_fill.c
- # src/tr_fix.c
- # src/tr_load.c
- # src/tr_out.c
- # src/tr_probe.c
- # src/tr_reviw.c
- # src/tr_setup.c
- # src/tr_solve.c
- # src/tr_sweep.c
- # This archive created: Tue Jan 26 22:51:12 1993
- export PATH; PATH=/bin:$PATH
- if test -f 'src/tr_clear.c'
- then
- echo shar: will not over-write existing file "'src/tr_clear.c'"
- else
- cat << \SHAR_EOF > 'src/tr_clear.c'
- /* tr_clear 12/30/92
- * Copyright 1983-1992 Albert Davis
- * Clears working arrays allocated by tralloc.
- * Saves the old time and last iteration. It is necessary to clear them
- * separately because they must be cleared for each new input, and the old
- * constants saved, and not reallocated. We cannot use free/calloc because it
- * would require setting new pointer tables.
- *
- * Also, a bunch of other stuff that is here only because of shared variables.
- */
- #include "ecah.h"
- #include "branch.h"
- #include "error.h"
- #include "mode.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void tr_clear(int);
- void trkeep(void);
- void trestor(void);
- void cmd_keep(void);
- void cmd_unkeep(void);
- /*--------------------------------------------------------------------------*/
- extern double last_time; /* time corresp to last voltage */
- extern double *volts; /* last voltage vector */
- extern double *recon,*imcon;
- extern double *oldcon; /* constant terms */
- extern double *reals, *imags; /* big array allocation base */
- extern int decomp; /* how far y-matrix decomposed */
- extern const struct status stats;
- extern const unsigned aspace; /* non-zero array elements */
- extern const double trtime; /* time at this iteration */
- extern const int inc_mode; /* make incremental changes */
- extern const int sim_mode; /* what type simulation is this */
- static int keepold; /* flag: keep old data */
- /*--------------------------------------------------------------------------*/
- void tr_clear(amt)
- int amt;
- {
- static double last_iter_time;
-
- if (!inc_mode){ /* Clear working array */
- (void)memset((void*)reals, 0, (size_t)aspace * sizeof(double));
- decomp = amt;
- }
- if (sim_mode == sTRAN && stats.iter[iSTEP] == 1){
- if (trtime > last_iter_time){
- int ii;
- for (ii = 1; ii <= stats.total_nodes; ii++){
- oldcon[ii] = imcon[ii];
- }
- last_iter_time = trtime;
- }else{
- /* don't save voltages. They're wrong !*/
- last_iter_time = trtime;
- }
- }
- if (!inc_mode){ /* Clear new right side */
- int ii;
- for (ii = 1; ii <= stats.total_nodes; ii++){
- recon[ii] = 0.;
- }
- }
- }
- /*--------------------------------------------------------------------------*/
- void trkeep()
- {
- if (!keepold){
- int ii;
- for (ii = 1; ii <= stats.total_nodes; ii++){
- volts[ii] = imcon[ii];
- }
- last_time = (trtime>0.) ? trtime : 0.;
- }
- }
- /*--------------------------------------------------------------------------*/
- void trestor()
- {
- int ii;
- for (ii = 1; ii <= stats.total_nodes; ii++){
- imcon[ii] = volts[ii];
- }
- }
- /*--------------------------------------------------------------------------*/
- void cmd_keep()
- {
- keepold = YES;
- }
- /*--------------------------------------------------------------------------*/
- void cmd_unkeep()
- {
- keepold= NO;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_conck.c'
- then
- echo shar: will not over-write existing file "'src/tr_conck.c'"
- else
- cat << \SHAR_EOF > 'src/tr_conck.c'
- /* tr_conck.c 12/08/91
- * Copyright 1983-1992 Albert Davis
- * Check convergence, and other stuff done after evaluation
- * to evaluate performance
- */
- #include "ecah.h"
- #include "branch.h"
- #include "convstat.h"
- #include "error.h"
- #include "io.h"
- #include "options.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- int conv_check(const branch_t*);
- int conchk(double,double,double);
- /*--------------------------------------------------------------------------*/
- extern const struct ioctrl io;
- extern const struct options opt;
- /*--------------------------------------------------------------------------*/
- /* conv_check: check branch for convergence
- * should be a macro, for speed
- */
- int conv_check(brh)
- const branch_t *brh;
- {
- int conv;
-
- conv = conchk(brh->y1.f0,brh->y0.f0,opt.abstol);
- if ((!io.suppresserrors) && (conv & cNONCONVERGE)){
- error(bPICKY,"%s: non-convergence: (f0) (%s,%s,%s)\n",
- printlabel(brh,NO),
- ftos(brh->y0.f0, "", 7, 0),
- ftos(brh->y1.f0, "", 7, 0),
- ftos(brh->y2.f0, "", 7, 0));
- if (conchk(brh->y1.f1,brh->y0.f1,opt.abstol) & cNONCONVERGE){
- error(bPICKY,"%s: non-convergence: (f1) (%s,%s,%s)\n",
- printlabel(brh,NO),
- ftos(brh->y0.f1, "", 7, 0),
- ftos(brh->y1.f1, "", 7, 0),
- ftos(brh->y2.f1, "", 7, 0));
- }else{
- error(bPICKY,"%s: f1 is ok\n", printlabel(brh,NO));
- }
- }
-
-
- if (!(conv & cNONCONVERGE)){
- conv = conchk(brh->y1.f1,brh->y0.f1,opt.abstol);
- if ((!io.suppresserrors) && (conv & cNONCONVERGE)){
- error(bPICKY,"%s: non-convergence: (f1 only) (%s,%s,%s)\n",
- printlabel(brh,NO),
- ftos(brh->y0.f1, "", 7, 0),
- ftos(brh->y1.f1, "", 7, 0),
- ftos(brh->y2.f1, "", 7, 0));
- }
- }
- return conv;
- }
- /*--------------------------------------------------------------------------*/
- /* conchk: check for convergence
- * should be macro.
- */
- int conchk(old,new,abstol)
- double old,new,abstol;
- {
- if (FABS(new-old) <= abstol)
- return cGOOD;
- else if (FABS(old) > abstol && inorder(opt.lowlim, new/old, opt.uplim))
- return cGOOD;
- else
- return cNONCONVERGE;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_fill.c'
- then
- echo shar: will not over-write existing file "'src/tr_fill.c'"
- else
- cat << \SHAR_EOF > 'src/tr_fill.c'
- /* tr_fill 03/26/92
- * Copyright 1983-1992 Albert Davis
- * Fill working matrix for transient and dc analysis
- * Returns convergence status.
- */
- #include "ecah.h"
- #include "branch.h"
- #include "convstat.h"
- #include "dev.h"
- #include "mode.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- int tr_fill(void);
- int tr_fill_rl(branch_t*);
- int tr_fill_ll(branch_t**);
- void tr_unfill_rl(branch_t*);
- /*--------------------------------------------------------------------------*/
- extern struct status stats;
- /*--------------------------------------------------------------------------*/
- /* tr_fill: process netlist, evaluate models, fill matrix, etc
- * clears matrix, re-fills it, checks for convergence
- * does not evaluate matrix
- */
- int tr_fill()
- {
- int conv; /* convergence flag */
-
- time_start(&(stats.load));
- conv = tr_fill_rl(firstbranch_dev());
- if (stats.iter[iSTEP] == 1)
- conv = cNONCONVERGE;
- time_stop(&(stats.load));
- return conv;
- }
- /*--------------------------------------------------------------------------*/
- /* tr_fill_rl: evaluate a list of models, fill matrix
- * evaluates a list (or sublist), checks convergence, etc.
- * argument is the head of the netlist.
- * recursively called to evaluate subcircuits
- */
- int tr_fill_rl(brh)
- branch_t *brh;
- {
- int conv;
- const branch_t *stop;
-
- conv = cGOOD;
- if (exists(brh)){
- stop = brh;
- do {
- conv |= dotr_branch(brh);
- } while (brh=nextbranch_dev(brh), brh != stop);
- }
- return conv;
- }
- /*--------------------------------------------------------------------------*/
- /* tr_fill_ll: linear list version of tr_fill_rl
- */
- int tr_fill_ll(bl)
- branch_t **bl;
- {
- int conv;
- branch_t *brh;
-
- conv = cGOOD;
- if (bl){
- for (brh = *bl; exists(brh); ++bl){
- conv |= dotr_branch(brh);
- }
- }
- return conv;
- }
- /*--------------------------------------------------------------------------*/
- /* tr_unfill_rl: remove evaluate a list of models from the matrix
- * recursively called to unevaluate subcircuits
- */
- void tr_unfill_rl(brh)
- branch_t *brh;
- {
- const branch_t *stop;
- if (exists(brh)){
- stop = brh;
- do {
- untr_branch(brh);
- } while (brh=nextbranch_dev(brh), brh != stop);
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_fix.c'
- then
- echo shar: will not over-write existing file "'src/tr_fix.c'"
- else
- cat << \SHAR_EOF > 'src/tr_fix.c'
- /* trfix 01/18/93
- * Copyright 1983-1992 Albert Davis
- * Takes care of nonlinearities, behavioral modeling, etc
- * in transient and dc analysis.
- */
- #include "ecah.h"
- #include "branch.h"
- #include "error.h"
- #include "expr.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void trfix0(branch_t*);
- void trfix1(branch_t*);
- static void trf_ac(const branch_t*,double**,int*,cpoly1_t*);
- static void trf_dc(const branch_t*,double**,int*,cpoly1_t*);
- static void trf_dctran(const branch_t*,double**,int*,cpoly1_t*);
- static void trf_frequency(const branch_t*,double**,int*,cpoly1_t*);
- static void trf_period(const branch_t*,double**,int*,cpoly1_t*);
- static void trf_ramp(const branch_t*,double**,int*,cpoly1_t*);
- static void trf_time(const branch_t*,double**,int*,cpoly1_t*);
- static void trf_tran(const branch_t*,double**,int*,cpoly1_t*);
- static void trf_bandwidth(const branch_t*,double**,cpoly1_t*);
- static void trf_complex(const branch_t*,double**,cpoly1_t*);
- static void trf_cornerdown(const branch_t*,double**,cpoly1_t*);
- static void trf_cornerup(const branch_t*,double**,cpoly1_t*);
- static void trf_delay(const branch_t*,double**,cpoly1_t*);
- static void trf_exp(const branch_t*,double**,cpoly1_t*);
- static void trf_expterm(const branch_t*,double**,cpoly1_t*);
- static void trf_generator(const branch_t*,double**,cpoly1_t*);
- static void trf_max(const branch_t*,double**,cpoly1_t*);
- static void trf_netfunc(const branch_t*,double**,cpoly1_t*);
- static void trf_notch(const branch_t*,double**,cpoly1_t*);
- static void trf_numeric(const branch_t*,double**,cpoly1_t*);
- static void trf_offset(const branch_t*,double**,cpoly1_t*);
- static void trf_polar(const branch_t*,double**,cpoly1_t*);
- static void trf_polyterm(const branch_t*,double**,cpoly1_t*);
- static void trf_pulse(const branch_t*,double**,cpoly1_t*);
- static void trf_pwl(const branch_t*,double**,cpoly1_t*);
- static void trf_sffm(const branch_t*,double**,cpoly1_t*);
- static void trf_sin(const branch_t*,double**,cpoly1_t*);
- static void trf_tanh(const branch_t*,double**,cpoly1_t*);
- static void trf_ic(const branch_t*,double**,cpoly1_t*);
- static void trf_ii(const branch_t*,double**,cpoly1_t*);
- static void trf_iv(const branch_t*,double**,cpoly1_t*);
- static void trf_tempco(const branch_t*,double**,cpoly1_t*);
- /*--------------------------------------------------------------------------*/
- #define arg0 (arg[0][0])
- #define arg1 (arg[0][1])
- #define arg2 (arg[0][2])
- #define arg3 (arg[0][3])
- #define arg4 (arg[0][4])
- #define arg5 (arg[0][5])
- #define arg6 (arg[0][6])
- #define arg7 (arg[0][7])
-
- extern const double genout; /* the bench signal generator */
- extern const double trtime; /* transient analysis time */
-
- extern int in_curr; /* flag: initial current */
- extern int in_volt; /* flag: initial voltage */
- extern int in_cond; /* flag: generic initial condition */
- extern double init_curr; /* initial current */
- extern double init_volt; /* initial voltage */
- extern double init_cond; /* generic initial condition */
-
- static int skip;
- static double periodtime; /* time since beginning of period */
- static double reltime; /* time since event */
- /*--------------------------------------------------------------------------*/
- void trfix0(brh)
- branch_t *brh;
- {
- brh->y0.f0 = NOT_VALID;
- }
- /*--------------------------------------------------------------------------*/
- void trfix1(brh)
- branch_t *brh;
- {
- cpoly1_t y; /* return value */
- /* y.c1 is the slope, y.c0 is y intercept */
- skip = NO;
- periodtime = reltime = trtime;
- y.x = brh->y0.x;
- y.f1 = brh->val;
- y.c0 = 0.;
-
- if (brh->x){
- struct expr *x;
- double *arg;
- int *key;
-
- x = (struct expr*)brh->x;
- arg = x->args->args;
- for (key = x->keys->args; *key; key++){
- switch (*key){
- case eAC: trf_ac(brh,&arg,&skip,&y); break;
- case eDC: trf_dc(brh,&arg,&skip,&y); break;
- case eDCTRAN: trf_dctran(brh,&arg,&skip,&y); break;
- case eFREQUENCY: trf_frequency(brh,&arg,&skip,&y);break;
- case ePERIOD: trf_period(brh,&arg,&skip,&y); break;
- case eRAMP: trf_ramp(brh,&arg,&skip,&y); break;
- case eTIME: trf_time(brh,&arg,&skip,&y); break;
- case eTRAN: trf_tran(brh,&arg,&skip,&y); break;
-
- case eBANDWIDTH: trf_bandwidth(brh,&arg,&y); break;
- case eCOMPLEX: trf_complex(brh,&arg,&y); break;
- case eCORNERDOWN: trf_cornerdown(brh,&arg,&y); break;
- case eCORNERUP: trf_cornerup(brh,&arg,&y); break;
- case eDELAY: trf_delay(brh,&arg,&y); break;
- case eEXP: trf_exp(brh,&arg,&y); break;
- case eEXPTERM: trf_expterm(brh,&arg,&y); break;
- case eGENERATOR: trf_generator(brh,&arg,&y); break;
- case eMAX: trf_max(brh,&arg,&y); break;
- case eNETFUNC: trf_netfunc(brh,&arg,&y); break;
- case eNOTCH: trf_notch(brh,&arg,&y); break;
- case eNUMERIC: trf_numeric(brh,&arg,&y); break;
- case eOFFSET: trf_offset(brh,&arg,&y); break;
- case ePOLAR: trf_polar(brh,&arg,&y); break;
- case ePOLYTERM: trf_polyterm(brh,&arg,&y); break;
- case ePULSE: trf_pulse(brh,&arg,&y); break;
- case ePWL: trf_pwl(brh,&arg,&y); break;
- case eSFFM: trf_sffm(brh,&arg,&y); break;
- case eSIN: trf_sin(brh,&arg,&y); break;
- case eTANH: trf_tanh(brh,&arg,&y); break;
-
- case eIC: trf_ic(brh,&arg,&y); break;
- case eII: trf_ii(brh,&arg,&y); break;
- case eIV: trf_iv(brh,&arg,&y); break;
- case eTEMPCO: trf_tempco(brh,&arg,&y); break;
-
- default: error(bWARNING, "%s: undefined function: %d\n", printlabel(brh,NO), *key); break;
- }
- }
- }
- brh->y0.x = y.x;
- brh->y0.f0 = y.c0 + y.x * y.f1;
- brh->y0.f1 = y.f1;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_ac: keyword: ac
- * following args for ac analysis only
- * here : skip them
- */
- /*ARGSUSED*/
- static void trf_ac(brh,arg,skip,y) /* no args */
- const branch_t *brh;
- double **arg;
- int *skip;
- cpoly1_t* y;
- {
- *skip = YES;
- *arg += aAC;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_dc: keyword: dc
- * following args for dc and transient analysis
- */
- /*ARGSUSED*/
- static void trf_dc(brh,arg,skip,y) /* no args */
- const branch_t *brh;
- double **arg;
- int *skip;
- cpoly1_t *y;
- {
- y->f1 = y->c0 = 0.;
- *skip = NO;
- *arg += aDC;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_dctran: keyword: dctran
- * following args for dc and transient analysis
- * this does apply to initial conditions.
- */
- /*ARGSUSED*/
- static void trf_dctran(brh,arg,skip,y) /* no args */
- const branch_t *brh;
- double **arg;
- int *skip;
- cpoly1_t* y;
- {
- y->f1 = y->c0 = 0.;
- *skip = NO;
- *arg += aDCTRAN;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_frequency: keyword: frequency
- * the value is frequency dependent (ac only)
- * works only in ac analysis, otherwise could be non-causal.
- */
- /*ARGSUSED*/
- static void trf_frequency(brh,arg,skip,y) /* arg0 = test freq */
- const branch_t *brh;
- double **arg;
- int *skip;
- cpoly1_t *y;
- {
- *skip = YES;
- *arg += aFREQUENCY;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_period: keyword: period
- * the component is periodic in time
- * periodtime and reltime are reset every period
- * all time dependencies are based on reltime and periodtime
- * for sensible behavior, this key should be first.
- * implies that following args for transient analysis only.
- */
- /*ARGSUSED*/
- static void trf_period(brh,arg,skip,y) /* arg0 = period */
- const branch_t *brh;
- double **arg;
- int *skip;
- cpoly1_t *y;
- {
- if (trtime >= 0.){ /* if transient analysis */
- y->f1 = y->c0 = 0.;
- *skip = NO;
- periodtime = reltime = (arg0 == 0.) ? trtime : fmod(trtime, arg0);
- }else{
- *skip = YES;
- }
- *arg += aPERIOD;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void trf_ramp(brh,arg,skip,y)
- const branch_t *brh;
- double **arg;
- int *skip;
- cpoly1_t *y;
- {
- error(bWARNING,"ramp not implemented: %s\n", printlabel(brh,NO));
- *arg += aRAMP;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_time: keyword: time
- * following args take effect at the given time (switch)
- * obviously, transient only.
- */
- /*ARGSUSED*/
- static void trf_time(brh,arg,skip,y) /* arg0 = switch time */
- const branch_t *brh;
- double **arg;
- int *skip;
- cpoly1_t *y;
- {
- if (periodtime >= arg0){
- y->f1 = y->c0 = 0.;
- reltime = periodtime - arg0;
- *skip = NO;
- }else{
- *skip = YES;
- }
- *arg += aTIME;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_tran: keyword: transient
- * following args for transient analysis only.
- * applies to the dc analysis that computes initial conditions,
- * but not the steady state dc analysis.
- */
- /*ARGSUSED*/
- static void trf_tran(brh,arg,skip,y) /* no args */
- const branch_t *brh;
- double **arg;
- int *skip;
- cpoly1_t *y;
- {
- if (trtime >= 0.){ /* if transient analysis */
- y->f1 = y->c0 = 0.;
- *skip = NO;
- }else{
- *skip = YES;
- }
- *arg += aTRAN;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_bandwidth: function: bandwidth
- * gain block, with a bandwidth. (ac only)
- * bad design: should be keyword instead.
- * not implemented in transient analysis
- * but could be as R-C or similar
- */
- static void trf_bandwidth(brh,arg,y) /* arg0 = dc gain */
- const branch_t *brh; /* arg1 = 3 db freq. */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- y->f1 += arg0;
- if (trtime > 0.)
- error(bPICKY,"%s: bandwidth not supported in transient analysis\n",printlabel(brh,NO));
- }
- *arg += aBANDWIDTH;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_complex: function: complex
- * complex value, cartesian coordinates, in frequency domain (ac only)
- * not possible in transient or dc because would be non-causal
- */
- static void trf_complex(brh,arg,y) /* arg0 = real part */
- const branch_t *brh; /* arg1 = imaginary part */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- y->f1 += arg0;
- error(bPICKY, "non-causal circuit: %s\n", printlabel(brh,NO));
- }
- *arg += aCOMPLEX;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_cornerdown: function: cornerdown
- * piecewise linear function:
- * output is 0 for in >= arg1
- * derivative is arg0 for in <= arg1
- */
- static void trf_cornerdown(brh,arg,y) /* arg0 = active slope */
- const branch_t *brh; /* arg1 = break point */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip && y->x < arg1){
- y->f1 += arg0;
- y->c0 -= arg1 * arg0;
- }
- *arg += aCORNERDOWN;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_cornerup: function: cornerup
- * piecewise linear function:
- * output is 0 for in <= arg1
- * derivative is arg0 for in >= arg1
- */
- static void trf_cornerup(brh,arg,y) /* arg0 = active slope */
- const branch_t *brh; /* arg1 = break point */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip && y->x > arg1){
- y->f1 += arg0;
- y->c0 -= arg1 * arg0;
- }
- *arg += aCORNERUP;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_delay: function: delay
- * time delay (ac only)
- * not implemented, needs storage of past time values
- */
- static void trf_delay(brh,arg,y) /* arg0 = magnitude */
- const branch_t *brh; /* arg1 = delay */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- y->f1 += arg0;
- error(bPICKY,"%s: delay not supported in transient or analysis\n",printlabel(brh,NO));
- }
- *arg += aDELAY;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_exp: spice compatible function: exp
- * spice source exponential function: exponential function of time
- * known bugs: defaults wrong: could divide by zero
- */
- /*ARGSUSED*/
- static void trf_exp(brh,arg,y) /* arg0 = initial value */
- const branch_t *brh; /* arg1 = pulsed value */
- double **arg; /* arg2 = rise delay */
- cpoly1_t *y; /* arg3 = rise time const */
- { /* arg4 = fall delay */
- if (!skip){ /* arg5 = fall time const */
- y->f1 += arg0;
- if (reltime > arg2)
- y->f1 += (arg1 - arg0) * (1. - exp(-(reltime-arg2)/arg3));
- if (reltime > arg4)
- y->f1 += (arg0 - arg1) * (1. - exp(-(reltime-arg4)/arg5));
- }
- *arg += aEXP;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_expterm: function: expterm
- * exponent term, non-integer power term (not exponential)
- * like polyterm, but for non-integers
- * only works for positive input, because negative number raised to
- * non-integer power is usually complex.
- */
- static void trf_expterm(brh,arg,y) /* arg0 = coefficient */
- const branch_t *brh; /* arg1 = exponent */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip && y->x > 0.){
- double coeff;
- coeff = arg0 * pow(y->x,arg1-1);
- y->f1 += coeff * arg1;
- y->c0 += coeff * y->x * (1-arg1);
- }
- *arg += aEXPTERM;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_generator: function: generator
- * value is derived from the "signal generator" (generator command)
- * intended for fixed sources, as circuit input.
- * component specific period determines only whether to use this or not
- * it does not actually affect the operation of the signal generator
- */
- /*ARGSUSED*/
- static void trf_generator(brh,arg,y) /* arg0 = scale factor */
- const branch_t *brh;
- double **arg;
- cpoly1_t *y;
- {
- if (!skip)
- y->f1 += arg0 * genout;
- *arg += aGENERATOR;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_max: function: max
- * piecewise linear function: block that clips
- * bad design: should be keyword, so it can apply to the total part
- * should be able to specify upper and lower limits
- */
- static void trf_max(brh,arg,y) /* arg0 = normal value */
- const branch_t *brh; /* arg1 = output clip pt */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip && arg0 != 0.){
- double clip_input;
- clip_input = arg1/arg0;
- if (fabs(y->x-brh->y1.x) < fabs(y->x-brh->y2.x)*10.){ /* normal */
- if (y->x < -clip_input) /* -clip */
- y->c0 -= arg1;
- else if (y->x > clip_input) /* +clip */
- y->c0 += arg1;
- else /* linear */
- y->f1 += arg0;
- }else{ /* oscillating */
- /* don't skip middle region */
- if (y->x < -clip_input && brh->y1.x < clip_input)
- y->c0 -= arg1;
- else if (y->x > clip_input && brh->y1.x > -clip_input)
- y->c0 += arg1;
- else
- y->f1 += arg0;
- }
- }
- *arg += aMAX;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_netfunc: function: netfunction
- * gain block, nth order response. (ac only)
- * not implemented in transient analysis
- * but could be as R-L-C or similar
- */ /* arg0 = arg count */
- static void trf_netfunc(brh,arg,y) /* arg1 = dc gain */
- const branch_t *brh; /* arg3 = order of denom*/
- double **arg; /* arg* = coefs of denom*/
- cpoly1_t *y; /* arg* = coefs of numer*/
- {
- int argcount;
- argcount = (int)arg0;
-
- if (!skip){
- y->f1 += arg1;
- if (trtime > 0.)
- error(bPICKY,"%s: netfunction not supported in transient analysis\n",printlabel(brh,NO));
- }
- *arg += argcount;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_notch: function: notch
- * piecewise linear function: crossover notch, dead zone
- * symmetric around zero
- */
- static void trf_notch(brh,arg,y) /* arg0 = normal value */
- const branch_t *brh; /* arg1 = dead zone size */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- if (y->x > arg1){
- y->f1 += arg0;
- y->c0 -= arg1 * arg0;
- }else if (y->x < -arg1){
- y->f1 += arg0;
- y->c0 += arg1 * arg0;
- }
- }
- *arg += aNOTCH;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_numeric: simple numeric argument
- */
- /*ARGSUSED*/
- static void trf_numeric(brh,arg,y) /* arg0 = value */
- const branch_t *brh;
- double **arg;
- cpoly1_t *y;
- {
- if (!skip)
- y->f1 += arg0;
- *arg += aNUMERIC;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_offset: function: offset
- * fixed dc offset
- * bad design: should be keyword
- */
- /*ARGSUSED*/
- static void trf_offset(brh,arg,y) /* arg0 = gain */
- const branch_t *brh; /* arg1 = output offset */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- y->f1 += arg0;
- y->c0 += arg1 * arg0;
- }
- *arg += aOFFSET;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_polar: function: polar
- * complex value in polar coordinates, in frequency domain (ac only)
- * not possible in transient or dc because would be non-causal
- */
- static void trf_polar(brh,arg,y) /* arg0 = magnitude */
- const branch_t *brh; /* arg1 = phase */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- y->f1 += arg0;
- error(bPICKY, "non-causal circuit: %s\n", printlabel(brh,NO));
- }
- *arg += aPOLAR;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_polyterm: function: polyterm
- * polynomial term, one term in a polynomial
- * power must be integer, is rounded to nearest integer
- * caution: will divide by zero with zero input and negative exponent
- */
- static void trf_polyterm(brh,arg,y) /* arg0 = coefficient */
- const branch_t *brh; /* arg1 = exponent */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- int expo;
- expo = (int)floor(arg1+.5);
- if (expo == 0){
- y->c0 += arg0;
- }else{ /* (expo != 0) */
- double coeff;
- coeff = arg0 * ipow(y->x,expo-1);
- y->f1 += coeff * expo;
- y->c0 += coeff * y->x * (1-expo);
- }
- }
- *arg += aPOLYTERM;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_pulse: spice compatible function: pulse
- * spice pulse function (for sources)
- */
- /*ARGSUSED*/
- static void trf_pulse(brh,arg,y) /* arg0 = initial value */
- const branch_t *brh; /* arg1 = pulsed value */
- double **arg; /* arg2 = delay time */
- cpoly1_t *y; /* arg3 = rise time */
- { /* arg4 = fall time */
- /* arg5 = pulse width */
- /* arg6 = period */
- if (!skip){
- double pw;
- double time;
-
- pw = (arg5 == 0.) ? reltime : arg5;
- time = reltime;
- if (arg6 != 0.){
- while (time >= arg2+arg6){
- time -= arg6;
- }
- }
-
- if (time >= arg2+arg3+pw+arg4){ /* past pulse */
- y->f1 += arg0;
- }else if (time >= arg2+arg3+pw){ /* falling */
- double interp;
- interp = (time - (arg2+arg3+pw)) / arg4;
- y->f1 += arg1 + interp * (arg0 - arg1);
- }else if (time >= arg2+arg3){ /* pulse val */
- y->f1 += arg1;
- }else if (time >= arg2){ /* rising */
- double interp;
- interp = (time - arg2) / arg3;
- y->f1 += arg0 + interp * (arg1 - arg0);
- }else{ /* init val */
- y->f1 += arg0;
- }
- }
- *arg += aPULSE;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_pwl: spice compatible function: pwl
- * "piece-wise linear" point-plotting function of time.
- * BUG: different from SPICE when first point is not zero
- */
- /*ARGSUSED*/ /* arg0 = arg count */
- static void trf_pwl(brh,arg,y) /* arg1 = time */
- const branch_t *brh; /* arg2 = value */
- double **arg; /* etc. */
- cpoly1_t *y;
- {
- int argcount;
- argcount = (int)(arg[0][0]);
-
- if (!skip){
- int i;
- double lowtime;
- double hitime;
- double lowvalue;
- double hivalue;
-
- lowtime = 0.;
- lowvalue = arg[0][2];
- for (i=1;
- i < argcount && reltime > arg[0][i] && lowtime <= arg[0][i];
- /**/ i += 2){
- lowtime = arg[0][i];
- lowvalue = arg[0][i+1];
- }
-
- hitime = arg[0][i];
- hivalue = arg[0][i+1];
- if (i < argcount && hitime > lowtime){
- double ratio;
- ratio = (reltime - lowtime) / (hitime - lowtime);
- y->f1 += lowvalue + (hivalue - lowvalue) * ratio;
- }else{
- y->f1 += lowvalue;
- }
- }
- *arg += argcount;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_sffm: spice compatible function: sffm
- * single frequency frequency modulation
- */
- /*ARGSUSED*/
- static void trf_sffm(brh,arg,y) /* arg0 = dc offset */
- const branch_t *brh; /* arg1 = amplitude */
- double **arg; /* arg2 = carrier freq */
- cpoly1_t *y; /* arg3 = mod index */
- { /* arg4 = signal freq */
- if (!skip){
- double mod;
- mod = arg3 * sin(PI2*arg4*reltime);
- y->f1 += arg0 + arg1 * sin(PI2*arg2*reltime + mod);
- }
- *arg += aSFFM;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_sin: spice compatible function: sin
- * sinusoidal function, mainly for sources
- * value is decaying sinusoidal function of time
- */
- /*ARGSUSED*/
- static void trf_sin(brh,arg,y) /* arg0 = offset */
- const branch_t *brh; /* arg1 = amplitude */
- double **arg; /* arg2 = frequency */
- cpoly1_t *y; /* arg3 = delay */
- { /* arg4 = damping */
- if (!skip){
- y->f1 += arg0;
- if (reltime > arg3){
- double x;
- x = arg1 * sin(PI2*arg2*(reltime-arg3));
- if (arg4 != 0.)
- x *= exp(-(reltime-arg3)*arg4);
- y->f1 += x;
- }
- }
- *arg += aSIN;
- }
- /*--------------------------------------------------------------------------*/
- /* trf_tanh: function: tanh
- * piecewise linear function: block that clips
- * bad design: should be keyword, so it can apply to the total part
- * should be able to specify upper and lower limits
- */
- static void trf_tanh(brh,arg,y) /* arg0 = normal value */
- const branch_t *brh; /* arg1 = output clip pt */
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- if (arg1 != 0.){
- double aa;
- double cosine;
- aa = y->x * arg0/arg1;
- cosine = cosh(aa);
- y->f1 += arg0 / (cosine*cosine);
- y->c0 += arg1 * tanh(aa) - y->f1 * y->x;
- }
- /* else 0 */
- }
- *arg += aTANH;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void trf_ic(brh,arg,y)
- const branch_t *brh;
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- in_cond = YES;
- init_cond = arg0;
- }
- *arg += 1;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void trf_ii(brh,arg,y)
- const branch_t *brh;
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- in_curr = YES;
- init_curr = arg0;
- }
- *arg += 1;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void trf_iv(brh,arg,y)
- const branch_t *brh;
- double **arg;
- cpoly1_t *y;
- {
- if (!skip){
- in_volt = YES;
- init_volt = arg0;
- }
- *arg += 1;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void trf_tempco(brh,arg,y)
- const branch_t *brh;
- double **arg;
- cpoly1_t *y;
- {
- #ifdef NEVER
- tempco = arg0;
- #endif
- *arg += 1;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_load.c'
- then
- echo shar: will not over-write existing file "'src/tr_load.c'"
- else
- cat << \SHAR_EOF > 'src/tr_load.c'
- /* tr_load 03/11/92
- * Copyright 1983-1992 Albert Davis
- * Load matrix from pre-computed values
- */
- #include "ecah.h"
- #include "array.h"
- #include "branch.h"
- #include "error.h"
- #include "mode.h"
- #include "options.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void trloadsource(branch_t*);
- void trloadpassive(branch_t*);
- void trloadactive(branch_t*);
- void unloadsource(branch_t*);
- void unloadpassive(branch_t*);
- void unloadactive(branch_t*);
- /*--------------------------------------------------------------------------*/
- extern const struct options opt;
- extern struct status stats;
- extern int inc_mode; /* make incremental changes */
- extern double *recon; /* constant terms */
- /*--------------------------------------------------------------------------*/
- /* trloadsource: load source to right side vector
- */
- void trloadsource(brh)
- branch_t *brh;
- {
- double dc0;
- if (brh->loaditer == stats.iter[iTOTAL])
- error(bDANGER, "%s: double load\n", printlabel(brh,0));
- brh->loaditer = stats.iter[iTOTAL];
- if (inc_mode){
- dc0 = brh->m0.c0 - brh->m1.c0;
- }else{
- dc0 = brh->m0.c0;
- }
- if (dc0 != 0.){
- if (brh->n[OUT2].m != 0)
- recon[brh->n[OUT2].m] += dc0;
- if (brh->n[OUT1].m != 0)
- recon[brh->n[OUT1].m] -= dc0;
- }else if (0){
- error(bDANGER, "%s: useless load (c0)\n", printlabel(brh,0));
- }
- brh->m1 = brh->m0;
- }
- /*--------------------------------------------------------------------------*/
- /* trloadpassive: load passive element to matrix, and offset to right side
- * symmetric around diagonal: input == output
- * if's optimize for speed. could be done like trloadactive, with OUT for IN.
- */
- void trloadpassive(brh)
- branch_t *brh;
- {
- double dc0;
- double df1;
- if (brh->loaditer == stats.iter[iTOTAL])
- error(bDANGER, "%s: double load\n", printlabel(brh,0));
- brh->loaditer = stats.iter[iTOTAL];
- if (inc_mode){
- dc0 = brh->m0.c0 - brh->m1.c0;
- df1 = brh->m0.f1 - brh->m1.f1;
- }else{
- dc0 = brh->m0.c0;
- df1 = brh->m0.f1;
- }
- if (df1 != 0.){
- if (brh->n[OUT2].m != 0){
- *AAd(brh->n[OUT2].m,brh->n[OUT2].m) += df1;
- if (brh->n[OUT1].m != 0){
- *AAd(brh->n[OUT1].m,brh->n[OUT1].m) += df1;
- *AA(brh->n[OUT1].m,brh->n[OUT2].m) -= df1;
- *AA(brh->n[OUT2].m,brh->n[OUT1].m) -= df1;
- }
- }else if (brh->n[OUT1].m != 0){
- *AAd(brh->n[OUT1].m,brh->n[OUT1].m) += df1;
- }
- }else if (0){
- error(bDANGER, "%s: useless load (f1)\n", printlabel(brh,0));
- }
- if (dc0 != 0.){
- if (brh->n[OUT2].m != 0)
- recon[brh->n[OUT2].m] += dc0;
- if (brh->n[OUT1].m != 0)
- recon[brh->n[OUT1].m] -= dc0;
- }else if (0){
- error(bDANGER, "%s: useless load (c0)\n", printlabel(brh,0));
- }
- brh->m1 = brh->m0;
- }
- /*--------------------------------------------------------------------------*/
- /* trloadactive: load active element to matrix, and offset to right side
- * asymmetric around diagonal: input != output
- */
- void trloadactive(brh)
- branch_t *brh;
- {
- double dc0;
- double df1;
- if (brh->loaditer == stats.iter[iTOTAL])
- error(bDANGER, "%s: double load\n", printlabel(brh,0));
- brh->loaditer = stats.iter[iTOTAL];
- if (inc_mode){
- dc0 = brh->m0.c0 - brh->m1.c0;
- df1 = brh->m0.f1 - brh->m1.f1;
- }else{
- dc0 = brh->m0.c0;
- df1 = brh->m0.f1;
- }
- if (df1 != 0.){
- *re(brh->n[OUT1].m,brh->n[IN1].m) += df1;
- *re(brh->n[OUT2].m,brh->n[IN2].m) += df1;
- *re(brh->n[OUT1].m,brh->n[IN2].m) -= df1;
- *re(brh->n[OUT2].m,brh->n[IN1].m) -= df1;
- }else if (0){
- error(bDANGER, "%s: useless load (f1)\n", printlabel(brh,0));
- }
- if (dc0 != 0.){
- if (brh->n[OUT2].m != 0)
- recon[brh->n[OUT2].m] += dc0;
- if (brh->n[OUT1].m != 0)
- recon[brh->n[OUT1].m] -= dc0;
- }else if (0){
- error(bDANGER, "%s: useless load (c0)\n", printlabel(brh,0));
- }
- brh->m1 = brh->m0;
- }
- /*--------------------------------------------------------------------------*/
- /* unloadsource: unload source from right side vector
- */
- void unloadsource(brh)
- branch_t *brh;
- {
- double dc0;
- brh->loaditer = 0;
- brh->m0.c0 = brh->m0.f1 = 0.;
- if (inc_mode){
- inc_mode = BAD;
- dc0 = brh->m0.c0 - brh->m1.c0;
- }else{
- dc0 = brh->m0.c0;
- }
- if (dc0 != 0.){
- if (brh->n[OUT2].m != 0)
- recon[brh->n[OUT2].m] += dc0;
- if (brh->n[OUT1].m != 0)
- recon[brh->n[OUT1].m] -= dc0;
- }
- brh->m1 = brh->m0;
- }
- /*--------------------------------------------------------------------------*/
- /* unloadpassive: unload passive element and offset
- * symmetric around diagonal: input == output
- * if's optimize for speed. could be done like unloadactive, with OUT for IN.
- */
- void unloadpassive(brh)
- branch_t *brh;
- {
- double dc0;
- double df1;
- brh->loaditer = 0;
- brh->m0.c0 = brh->m0.f1 = 0.;
- if (inc_mode){
- inc_mode = BAD;
- dc0 = brh->m0.c0 - brh->m1.c0;
- df1 = brh->m0.f1 - brh->m1.f1;
- }else{
- dc0 = brh->m0.c0;
- df1 = brh->m0.f1;
- }
- if (df1 != 0.){
- if (brh->n[OUT2].m != 0){
- *AAd(brh->n[OUT2].m,brh->n[OUT2].m) += df1;
- if (brh->n[OUT1].m != 0){
- *AAd(brh->n[OUT1].m,brh->n[OUT1].m) += df1;
- *AA(brh->n[OUT1].m,brh->n[OUT2].m) -= df1;
- *AA(brh->n[OUT2].m,brh->n[OUT1].m) -= df1;
- }
- }else if (brh->n[OUT1].m != 0){
- *AAd(brh->n[OUT1].m,brh->n[OUT1].m) += df1;
- }
- }
- if (dc0 != 0.){
- if (brh->n[OUT2].m != 0)
- recon[brh->n[OUT2].m] += dc0;
- if (brh->n[OUT1].m != 0)
- recon[brh->n[OUT1].m] -= dc0;
- }
- brh->m1 = brh->m0;
- }
- /*--------------------------------------------------------------------------*/
- /* unloadactive: unload active element from matrix, and offset from right side
- * asymmetric around diagonal: input != output
- */
- void unloadactive(brh)
- branch_t *brh;
- {
- double dc0;
- double df1;
- brh->loaditer = 0;
- brh->m0.c0 = brh->m0.f1 = 0.;
- if (inc_mode){
- inc_mode = BAD;
- dc0 = brh->m0.c0 - brh->m1.c0;
- df1 = brh->m0.f1 - brh->m1.f1;
- }else{
- dc0 = brh->m0.c0;
- df1 = brh->m0.f1;
- }
- if (df1 != 0.){
- *re(brh->n[OUT1].m,brh->n[IN1].m) += df1;
- *re(brh->n[OUT2].m,brh->n[IN2].m) += df1;
- *re(brh->n[OUT1].m,brh->n[IN2].m) -= df1;
- *re(brh->n[OUT2].m,brh->n[IN1].m) -= df1;
- }
- if (dc0 != 0.){
- if (brh->n[OUT2].m != 0)
- recon[brh->n[OUT2].m] += dc0;
- if (brh->n[OUT1].m != 0)
- recon[brh->n[OUT1].m] -= dc0;
- }
- brh->m1 = brh->m0;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_out.c'
- then
- echo shar: will not over-write existing file "'src/tr_out.c'"
- else
- cat << \SHAR_EOF > 'src/tr_out.c'
- /* tr_out 01/26/93
- * Copyright 1983-1992 Albert Davis
- * tr,dc analysis output functions (and some ac)
- */
- #include "ecah.h"
- #include "branch.h"
- #include "dc.h"
- #include "io.h"
- #include "mode.h"
- #include "probh.h"
- #include "status.h"
- #include "tr.h"
- #include "worst.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void dc_out(const dc_t*);
- void tr_out(const transient_t*);
- void tr_head(double,double,int,char*);
- static void tr_print(double);
- /*--------------------------------------------------------------------------*/
- extern const struct ioctrl io;
- extern struct status stats;
-
- extern const probe_t *probelist[];
- extern const int sim_mode;
- extern const int worstcase;
- extern const complex_t *fodata; /* used as a flag */
- /*--------------------------------------------------------------------------*/
- /* dc_out: output the data, "keep" for ac reference
- * is separate from tr_out only because of old plot functions
- */
- void dc_out(dc)
- const dc_t *dc;
- {
- time_start(&(stats.output));
- if (dc->printnow){
- trkeep();
- plotdc(*dc->sweep[0]);
- tr_print(*dc->sweep[0]);
- stats.iter[iPRINTSTEP] = 0;
- stats.control[cSTEPS] = 0;
- }
- time_stop(&(stats.output));
- }
- /*--------------------------------------------------------------------------*/
- /* tr_out: output the data, "keep" for ac reference
- */
- void tr_out(tr)
- const transient_t *tr;
- {
- time_start(&(stats.output));
- if (tr->printnow){
- trkeep();
- plottr(tr->time);
- tr_print(tr->time);
- stats.iter[iPRINTSTEP] = 0;
- stats.control[cSTEPS] = 0;
- }
- time_stop(&(stats.output));
- }
- /*--------------------------------------------------------------------------*/
- /* tr_head: print column headings and draw plot borders
- */
- void tr_head(start,stop,linear,col1)
- double start;
- double stop;
- int linear;
- char *col1;
- {
- if (!plopen(sim_mode,start,stop,linear)){
- if (col1 && *col1)
- mprintf(io.where," %-10s", col1);
- if (probelist[sim_mode]){
- int ii;
- for (ii = 0; *probelist[sim_mode][ii].what; ii++){
- probe_t prb; /* to hide MSC BUG */
- prb = probelist[sim_mode][ii];
- mprintf(io.where," %-10.10s", probename(prb));
- }
- }
- mprintf(io.where,"\n");
- }
- }
- /*--------------------------------------------------------------------------*/
- /* tr_print: print the list of results (text form) to io.where
- * The argument is the first column (independent variable, aka "x")
- */
- static void tr_print(x)
- double x;
- {
- if (!io.ploton){
- if (x != NOT_VALID)
- mprintf(io.where,ftos(x," ",5,io.formaat));
- if (probelist[sim_mode]){
- int ii;
- for (ii = 0; *probelist[sim_mode][ii].what; ii++){
- double value;
- probe_t prb; /* to hide MSC BUG */
- prb = probelist[sim_mode][ii];
- value = trprobe(prb);
- mprintf(io.where,ftos(value," ",5,io.formaat));
- }
- }
- mprintf(io.where,"\n");
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_probe.c'
- then
- echo shar: will not over-write existing file "'src/tr_probe.c'"
- else
- cat << \SHAR_EOF > 'src/tr_probe.c'
- /* tr_probe 01/11/93
- * Copyright 1983-1992 Albert Davis
- * transient analysis probe
- */
- #include "ecah.h"
- #include "branch.h"
- #include "dev.h"
- #include "mode.h"
- #include "nodestat.h"
- #include "probh.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- double trprobe(probe_t);
- static double trprobe_node(probe_t);
- /*--------------------------------------------------------------------------*/
- extern const struct status stats;
- extern const struct nodestat *nstat;
- extern const double genout;
- extern const double temp;
- extern const double trtime;
- extern const int *nm;
- extern double *imcon;
- /*--------------------------------------------------------------------------*/
- double trprobe(prb)
- probe_t prb;
- {
- if (prb.p.node <= stats.total_nodes){
- return trprobe_node(prb);
- }else{
- return trprobe_branch(prb.p.brh,prb.what);
- }
- }
- /*--------------------------------------------------------------------------*/
- static double trprobe_node(prb)
- probe_t prb;
- {
- int dummy = 0;
-
- setmatch(prb.what,&dummy);
- if (rematch("ITer") && prb.p.node < iCOUNT){
- return (double)stats.iter[prb.p.node];
- }else if (rematch("Control") && prb.p.node < cCOUNT){
- return (double)stats.control[prb.p.node];
- }else if (rematch("GEnerator")){
- return genout;
- }else if (rematch("Temperature")){
- return temp + ABS_ZERO;
- }else if (rematch("TIme")){
- return trtime;
- }else if (prb.p.node > stats.total_nodes){
- return NOT_VALID;
- }else if (rematch("V")){
- return imcon[nm[prb.p.node]];
- }else if (rematch("Logic")){
- return logicval(nm[prb.p.node]);
- }else if (rematch("LAstchange")){
- return nstat[prb.p.node].lastchange;
- }else if (rematch("FInaltime")){
- return nstat[prb.p.node].finaltime;
- }else if (rematch("DIter")){
- return (double)nstat[prb.p.node].diter;
- }else if (rematch("AIter")){
- return (double)nstat[prb.p.node].aiter;
- }else{ /* bad parameter */
- return NOT_VALID;
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_reviw.c'
- then
- echo shar: will not over-write existing file "'src/tr_reviw.c'"
- else
- cat << \SHAR_EOF > 'src/tr_reviw.c'
- /* tr_rev 12/31/92
- * Copyright 1983-1992 Albert Davis
- * review the solution after solution at a time point
- * Set up events, evaluate logic inputs, truncation error.
- * Adjust step size.
- */
- #include "ecah.h"
- #include "branch.h"
- #include "error.h"
- #include "dev.h"
- #include "mode.h"
- #include "options.h"
- #include "status.h"
- #include "tr.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void tr_review(transient_t*);
- double tr_review_rl(branch_t*);
- double tr_review_ll(branch_t**);
- /*--------------------------------------------------------------------------*/
- extern const struct options opt;
- extern struct status stats;
- extern int sim_phase; /* simulation phase (init_dc, tran, ...) */
- /*--------------------------------------------------------------------------*/
- void tr_review(tr)
- transient_t *tr;
- {
- static double rtime;
- double tetime;
- double adt; /* actual dt */
- double rdt; /* review dt */
-
- time_start(&(stats.review));
- ++stats.iter[iTOTAL];
- if (sim_phase == pINIT_DC){
- rtime = 0.;
- adt = rdt = tr->maxdt;
- }else{
- rdt = rtime - tr->oldtime;
- adt = tr->time - tr->oldtime;
- }
- if (adt > rdt + opt.mrt)
- error(bDANGER, "internal error: step control (%g,%g)\n", adt, rdt);
-
- if (stats.iter[iSTEP] >= opt.itl[4]){ /* too many iterations */
- rtime = tr->oldtime + adt / 8.; /* try again */
- tr->control = scITER_R;
- }else if (stats.iter[iSTEP] > opt.itl[3]){ /* too many iterations */
- rtime = tr->time + adt; /* no growth */
- tr->control = scITER_A;
- }else{ /* too few iterations */
- rtime = tr->time + tr->maxdt; /* use bigger steps */
- tr->control = scSKIP;
- if (rtime > tr->time + rdt * 2){
- rtime = tr->time + rdt * 2; /* limit to rdt*2 */
- tr->control = scRDT;
- }
- if (rtime > tr->time + adt * 2 && rtime > tr->time + rdt){
- if (rdt > adt * 2)
- rtime = tr->time + rdt;
- else /* limit to max(rdt,atd*2) */
- rtime = tr->time + adt * 2;
- tr->control = scADT;
- }
- }
- tetime = tr_review_rl(firstbranch_dev()); /* trunc error, etc. */
- time_stop(&(stats.review));
- if (tetime < rtime){
- tr->control = scTE;
- tr->approxtime = tetime;
- }else{
- tr->approxtime = rtime;
- }
- }
- /*--------------------------------------------------------------------------*/
- double tr_review_rl(brh)
- branch_t *brh;
- {
- double devicetime, worsttime;
- const branch_t *stop;
-
- worsttime = BIGBIG;
- if (exists(brh)){
- stop = brh;
- do {
- devicetime = tr_review_branch(brh);
- if (devicetime < worsttime)
- worsttime = devicetime;
- } while (brh=nextbranch_dev(brh), brh != stop);
- }
- return worsttime;
- }
- /*--------------------------------------------------------------------------*/
- double tr_review_ll(bl)
- branch_t **bl;
- {
- double devicetime, worsttime;
- branch_t *brh;
-
- worsttime = BIGBIG;
- if (bl){
- for (brh = *bl; exists(brh); ++bl){
- devicetime = tr_review_branch(brh);
- if (devicetime < worsttime)
- worsttime = devicetime;
- }
- }
- return worsttime;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_setup.c'
- then
- echo shar: will not over-write existing file "'src/tr_setup.c'"
- else
- cat << \SHAR_EOF > 'src/tr_setup.c'
- /* tr_setup 12/29/92
- * Copyright 1983-1992 Albert Davis
- * set up transient and fourier analysis
- */
- #include "ecah.h"
- #include "argparse.h"
- #include "error.h"
- #include "io.h"
- #include "mode.h"
- #include "options.h"
- #include "tr.h"
- #include "worst.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void tr_setup(const char*,int*,transient_t*);
- void fo_setup(const char*,int*,fourier_t*);
- static long to_pow_of_2(double);
- static void tr_options(const char*,int*,transient_t*);
- /*--------------------------------------------------------------------------*/
- extern struct ioctrl io;
- extern const struct options opt;
- extern const double last_time; /* time to restart at (set by trkeep) */
- extern int sim_mode; /* simulation type (AC, DC, ...) */
- extern int worstcase; /* worst case, monte carlo mode (enum type, worst.h)*/
- extern double temp; /* actual ambient temperature, kelvin */
- extern int stiff; /* flag: use stiff integration method */
- /*--------------------------------------------------------------------------*/
- /* tr_setup: transient analysis: parse command string and set options
- * (options set by call to tr_options)
- */
- void tr_setup(cmd,cnt,tr)
- const char *cmd;
- int *cnt;
- transient_t *tr;
- {
- double oldstart, oldstop, oldrange;
-
- oldstart = tr->start;
- oldstop = tr->stop;
- oldrange = oldstop - oldstart;
-
- tr->cont = YES;
- if ( isdigit(cmd[*cnt]) || cmd[*cnt]=='.' ){
- double arg1,arg2,arg3;
- arg1 = fabs(ctof(cmd,cnt));
- arg2 = fabs(ctof(cmd,cnt));
- arg3 = fabs(ctof(cmd,cnt));
- if (arg3 != 0.){ /* 3 args: all */
- if (arg1 == 0. || arg1 > arg3){ /* eca (logical) order: */
- tr->start = arg1; /* start stop step */
- tr->stop = arg2;
- tr->step = arg3;
- }else{ /* spice (illogical) order */
- tr->start = arg3; /* step stop start */
- tr->stop = arg2;
- tr->step = arg1;
- }
- }else if (arg2 != 0.){ /* 2 args */
- if (arg1 == 0.){ /* 2 args: start, stop */
- tr->start = arg1;
- tr->stop = arg2;
- /* tr->step unchanged */
- }else if (arg1 >= arg2){ /* 2 args: stop, step */
- tr->start = last_time;
- tr->stop = arg1;
- tr->step = arg2;
- }else{ /* arg1 < arg2 */ /* 2 args: step, stop */
- tr->start = arg3; /* 0 */ /* spice order */
- tr->stop = arg2;
- tr->step = arg1;
- }
- }else if (arg1 > last_time){ /* 1 arg: stop */
- tr->start = last_time;
- tr->stop = arg1;
- /* tr->step unchanged */
- }else if (arg1 == 0.){ /* 1 arg: start */
- tr->start = 0.;
- tr->stop = oldrange;
- /* tr->step unchanged */
- }else{ /* arg1 < last_time, but not 0 */ /* 1 arg: step */
- tr->start = last_time;
- tr->stop = last_time + oldrange;
- tr->step = arg1;
- }
- }else{ /* no args */
- tr->start = last_time;
- tr->stop = last_time + oldrange;
- /* tr->step unchanged */
- }
- tr_options(cmd,cnt,tr);
- if (tr->start < last_time || last_time <= 0.){
- tr->cont = NO;
- tr->oldtime = tr->time = 0.;
- }else{
- tr->cont = YES;
- tr->oldtime = tr->time = last_time;
- }
- if ( tr->step==0. )
- error(bERROR, "time step = 0\n");
- }
- /*--------------------------------------------------------------------------*/
- /* fo_setup: fourier analysis: parse command string and set options
- * (options set by call to tr_options)
- */
- void fo_setup(cmd,cnt,fo)
- const char *cmd;
- int *cnt;
- fourier_t *fo;
- {
- double oldstop;
- long points;
-
- oldstop = fo->stop;
- fo->tr.cont = YES;
- if ( isdigit(cmd[*cnt]) || cmd[*cnt]=='.' ){
- double arg1,arg2,arg3;
- arg1 = fabs(ctof(cmd,cnt));
- arg2 = fabs(ctof(cmd,cnt));
- arg3 = fabs(ctof(cmd,cnt));
- if (arg3 != 0.){ /* 3 args: all */
- fo->start = arg1;
- fo->stop = arg2;
- fo->step = arg3;
- }else if (arg2 != 0.){ /* 2 args */
- if (arg1 >= arg2){ /* 2 args: stop, step */
- /* fo->start unchanged */
- fo->stop = arg1;
- fo->step = arg2;
- }else{ /* arg1 < arg2 */ /* 2 args: start, stop */
- fo->start = arg1;
- fo->stop = arg2;
- /* fo->step unchanged */
- }
- }else if (arg1 > oldstop/8 ){ /* 1 arg: stop */
- /* fo->start unchanged */
- fo->stop = arg1;
- /* fo->step unchanged */
- }else if (arg1 == 0.){ /* 1 arg: start */
- fo->start = 0.;
- /* fo->stop unchanged */
- /* fo->step unchanged */
- }else{ /* arg1 < oldstep/8, but not 0 */ /* 1 arg: step */
- /* fo->start unchanged */
- /* fo->stop unchanged */
- fo->step = arg1;
- }
- }
- /* else (no args) : no change */
-
- if ( fo->step==0. || fo->stop==0. )
- error(bERROR, "frequency step = 0\n");
- tr_options(cmd,cnt,&fo->tr);
- points = to_pow_of_2(fo->stop*2 / fo->step);
- fo->tr.time = fo->tr.start = ((fo->tr.cold) ? 0. : last_time);
- fo->tr.stop = fo->tr.time + 1/fo->step;
- fo->tr.step = (fo->tr.stop - fo->tr.start) / points;
- foinit(points);
- }
- /*--------------------------------------------------------------------------*/
- /* to_pow_of_2: round up to nearest power of 2
- * example: z=92 returns 128
- */
- static long to_pow_of_2(z)
- double z;
- {
- long x,y;
- x = (long)floor(z);
- for (y=1; x>0; x>>=1 )
- y<<=1;
- return y;
- }
- /*--------------------------------------------------------------------------*/
- /* tr_options: set options common to transient and fourier analysis
- */
- static void tr_options(cmd,cnt,tr)
- const char *cmd;
- int *cnt;
- transient_t *tr;
- {
- io.where |= io.mstdout;
- temp = opt.tempamb;
- io.ploton = io.plotset;
- tr->all = stiff = tr->echo = tr->cold = tr->watch = worstcase = NO;
- for (;;){
- if (argparse(cmd,cnt,REPEAT,
- "ACMAx", aENUM, &worstcase, wMAXAC,
- "ACMIn", aENUM, &worstcase, wMINAC,
- "ALl", aENUM, &tr->all, YES,
- "Ambient", aODOUBLE, &temp, opt.tempamb,
- "Cold", aENUM, &tr->cold, YES,
- "DCMAx", aENUM, &worstcase, wMAXDC,
- "DCMIn", aENUM, &worstcase, wMINDC,
- "Echo", aENUM, &tr->echo, YES,
- "LAg", aENUM, &worstcase, wLAG,
- "LEad", aENUM, &worstcase, wLEAD,
- "NOPlot", aENUM, &io.ploton, NO,
- "PLot", aENUM, &io.ploton, YES,
- "RAndom", aENUM, &worstcase, wRAND,
- "Reftemp", aODOUBLE, &temp, opt.tnom,
- "SEnsitivity", aENUM, &worstcase, wSENS,
- "SKip", aUINT, &tr->skip,
- "STiff", aENUM, &stiff, YES,
- "Temperature", aODOUBLE, &temp, -ABS_ZERO,
- "WAtch", aENUM, &tr->watch, YES,
- ""))
- ;
- else if (outset(cmd,cnt,(char*)NULL,((sim_mode==sTRAN)?"tr ":"fo ")))
- ;
- else{
- syntax(cmd,cnt,bWARNING);
- break;
- }
- }
- if (tr->skip < 1)
- tr->skip = 1;
- tr->maxdt = tr->step / tr->skip;
- initio(io.where,io.whence);
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_solve.c'
- then
- echo shar: will not over-write existing file "'src/tr_solve.c'"
- else
- cat << \SHAR_EOF > 'src/tr_solve.c'
- /* tr_solve 12/29/92
- * Copyright 1983-1992 Albert Davis
- * solve one step or a transient analysis
- */
- #include "ecah.h"
- #include "convstat.h"
- #include "error.h"
- #include "io.h"
- #include "mode.h"
- #include "options.h"
- #include "status.h"
- #include "tr.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- int tr_solve(int);
- /*--------------------------------------------------------------------------*/
- extern struct ioctrl io;
- extern const struct options opt;
- extern struct status stats;
-
- extern int errorcount; /* count of errors this iteration */
- extern int inc_mode; /* make incremental changes */
- extern int sim_mode; /* simulation type (AC, DC, ...) */
- extern int currents_bad;
- /*--------------------------------------------------------------------------*/
- int tr_solve(itl) /* solve one time step */
- int itl;
- {
- int conv;
-
- stats.iter[iSTEP] = 0;
- ++stats.control[cSTEPS];
- errorcount = 0;
-
- for (;;){
- ++stats.iter[iPRINTSTEP];
- ++stats.iter[iSTEP];
- ++stats.iter[sim_mode];
- ++stats.iter[iTOTAL];
- tr_clear((inc_mode)?stats.total_nodes:0);
- conv = tr_fill();
- if (conv == cGOOD)
- break;
- solve();
- if (stats.iter[iSTEP] >= opt.itl[8]){
- io.suppresserrors = NO;
- }
- if (stats.iter[iSTEP] >= itl){
- break;
- }
- inc_mode = (inc_mode == BAD || stats.iter[iSTEP] == opt.itl[3])
- ? NO : opt.incmode;
- currents_bad = NO;
- }
- return conv;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/tr_sweep.c'
- then
- echo shar: will not over-write existing file "'src/tr_sweep.c'"
- else
- cat << \SHAR_EOF > 'src/tr_sweep.c'
- /* tr_sweep.c 01/11/93
- * Copyright 1983-1992 Albert Davis
- * sweep time and simulate. output results.
- * manage event queue
- */
- #include "ecah.h"
- #include "branch.h"
- #include "convstat.h"
- #include "error.h"
- #include "io.h"
- #include "mode.h"
- #include "options.h"
- #include "status.h"
- #include "tr.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void tr_sweep(transient_t*);
- void new_event(double);
- static void tr_first(transient_t*);
- static int tr_next(transient_t*);
- /*--------------------------------------------------------------------------*/
- extern struct ioctrl io;
- extern const struct options opt;
- extern struct status stats;
- extern const char e_int[];
-
- extern double trtime; /* transient analysis time */
- extern double genout; /* output of "signal generator" (ckt input) */
- extern int sim_phase; /* simulation phase (init_dc, tran, ...) */
- extern int currents_bad;
-
- static double events[MAXEVENTCOUNT]; /* the event queue */
- static int nei; /* next event index */
- static int eeq; /* end of event queue */
- static double nexttick; /* next pre-scheduled user "event" */
- /*--------------------------------------------------------------------------*/
- void tr_sweep(tr)
- transient_t *tr;
- {
- int conv;
-
- tr_head(tr->start, tr->stop, YES/*linear*/, "Time");
- currents_bad = YES;
- if (tr->cont){ /* use the data from last time */
- trestor();
- }
-
- tr_first(tr);
- sim_phase = pINIT_DC;
- genout = gen();
- io.suppresserrors = !tr->watch;
- conv = tr_solve(opt.itl[1]);
- if (conv != cGOOD)
- error(bWARNING, "did not converge\n");
- tr_review(tr);
- tr_out(tr);
-
- while (tr_next(tr)){
- sim_phase = pTRAN;
- genout = gen();
- io.suppresserrors = !tr->watch;
- conv = tr_solve(opt.itl[4]);
- tr_review(tr);
- if (conv != cGOOD || tr->approxtime <= tr->time)
- tr->printnow = NO;
- tr->printnow |= tr->all;
- tr_out(tr);
- }
- }
- /*--------------------------------------------------------------------------*/
- void new_event(etime)
- double etime;
- {
- int ii, jj, kk;
-
- /*time_start(&(stats.review));*/
- for (ii = nei; ii != eeq; ii = (ii+1)%MAXEVENTCOUNT){
- if (etime <= events[ii])
- break;
- }
- for (jj = eeq; jj != ii; jj = kk){
- kk = jj - 1;
- if (kk < 0)
- kk += MAXEVENTCOUNT;
- events[jj] = events[kk];
- }
- events[ii] = etime;
- eeq = (eeq+1)%MAXEVENTCOUNT;
- if (eeq == nei)
- error(bERROR, e_int, "event queue overflow");
- if (opt.foooo == 3){
- printf("(%d,%d) ", nei, eeq);
- for (ii = nei; ii != eeq; ii = (ii+1)%MAXEVENTCOUNT)
- printf("%g ", events[ii]);
- printf("\n");
- }
- /*time_stop(&(stats.review));*/
- }
- /*--------------------------------------------------------------------------*/
- static void tr_first(tr)
- transient_t *tr;
- {
- /* usually, tr->time, tr->oldtime == 0, from tr_setup */
- time_start(&(stats.review));
- nexttick = tr->time + tr->step; /* set next user step */
- nei = eeq; /* empty the queue */
- trtime = tr->time;
- tr->printnow = YES;
- time_stop(&(stats.review));
- }
- /*--------------------------------------------------------------------------*/
- static int tr_next(tr)
- transient_t *tr;
- {
- double newtime;
-
- time_start(&(stats.review));
- /* tr_review(tr); */ /* trunc error, etc. */
-
- newtime = nexttick; /* user time steps */
- stats.control[cSTEPCAUSE] = scUSER;
-
- if (nei != eeq && events[nei] <= newtime){ /* the event queue */
- newtime = events[nei];
- stats.control[cSTEPCAUSE] = scEVENTQ;
- }
-
- if (tr->approxtime < newtime - opt.mrt){
- if (tr->approxtime < (newtime + tr->time) / 2.){
- newtime = tr->approxtime;
- stats.control[cSTEPCAUSE] = tr->control;
- }else{
- newtime = (newtime + tr->time) / 2.;
- stats.control[cSTEPCAUSE] = scHALF;
- }
- }
-
- if (nexttick < newtime + opt.mrt){ /* advance user time */
- tr->printnow = YES; /* print if user step */
- nexttick += tr->step;
- }else{
- tr->printnow = tr->all;
- }
-
- while (nei != eeq && events[nei] <= newtime){/* advance event queue */
- nei = (nei+1)%MAXEVENTCOUNT;
- }
-
- if (newtime < tr->time + opt.mrt){
- if (newtime < tr->time){
- error(bTRACE, "backwards time step\n");
- stats.control[cSTEPCAUSE] += scREJECT;
- if (newtime < (nexttick - tr->step)){
- error(bTRACE, "user step rejected\n");
- nexttick -= tr->step;
- }
- if (newtime < tr->oldtime){
- error(bDANGER, "very backward time step\n");
- newtime = tr->oldtime + opt.mrt;
- }
- }else if (newtime == tr->time){
- error(bWARNING, "zero time step\n");
- newtime = tr->time + opt.mrt;
- stats.control[cSTEPCAUSE] += scZERO;
- }else{
- error(bWARNING, "time step too small\n");
- newtime = tr->time + opt.mrt;
- stats.control[cSTEPCAUSE] += scSMALL;
- }
- }
-
- if (newtime > tr->time){
- tr->oldtime = tr->time;
- }else if (newtime == tr->time){
- error(bDANGER, e_int, "perpetual zero time step");
- newtime += opt.mrt;
- stats.control[cSTEPCAUSE] += scNO_ADVANCE;
- tr->oldtime = tr->time; /* if (newtime < tr->time) */
- } /* do not advance oldtime */
-
- trtime = tr->time = newtime;
- time_stop(&(stats.review));
- return (tr->time <= tr->stop + opt.mrt);
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-