home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-28 | 60.6 KB | 1,983 lines |
- Path: sparky!uunet!ferkel.ucsb.edu!taco!rock!stanford.edu!ames!haven.umd.edu!darwin.sura.net!bogus.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 10/20
- Message-ID: <1993Jan27.040639.11348@rbc.uucp>
- Date: 27 Jan 93 04:06:39 GMT
- Sender: al@rbc.uucp (Al Davis)
- Organization: Huh?
- Lines: 1972
-
- #! /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/ac.c
- # src/ac_clear.c
- # src/ac_fill.c
- # src/ac_fix.c
- # src/ac_load.c
- # src/ac_out.c
- # src/ac_probe.c
- # src/ac_setup.c
- # src/ac_sweep.c
- # src/ac_z.c
- # src/allocate.c
- # src/argparse.c
- # src/array.c
- # This archive created: Tue Jan 26 22:50:59 1993
- export PATH; PATH=/bin:$PATH
- if test -f 'src/ac.c'
- then
- echo shar: will not over-write existing file "'src/ac.c'"
- else
- cat << \SHAR_EOF > 'src/ac.c'
- /* ac 12/29/92
- * Copyright 1983-1992 Albert Davis
- * ac analysis top
- */
- #include "ecah.h"
- #include "ac.h"
- #include "mode.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void cmd_ac(const char*,int*);
- /*--------------------------------------------------------------------------*/
- extern struct status stats;
- extern ac_t ac;
- extern int run_mode; /* variations on handling of dot cmds */
- extern int sim_mode; /* simulation type (AC, DC, ...) */
- /*--------------------------------------------------------------------------*/
- void cmd_ac(cmd,cnt)
- const char *cmd;
- int *cnt;
- {
- sim_mode = sAC;
- time_zstart(&(stats.total));
- time_zstart(&(stats.ac));
-
- allocate(sim_mode);
- ac_setup(cmd,cnt,&ac);
- if (run_mode != rEXECUTE)
- return;
- ac_sweep(&ac);
-
- time_stop(&(stats.ac));
- time_stop(&(stats.total));
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_clear.c'
- then
- echo shar: will not over-write existing file "'src/ac_clear.c'"
- else
- cat << \SHAR_EOF > 'src/ac_clear.c'
- /* acclear 04/02/92
- * Copyright 1983-1992 Albert Davis
- Clears working arrays allocated by acalloc. It is
- necessary to clear them separately because they must be cleared for each new
- frequency, but not reallocated. We cannot use free/calloc because it would
- require setting new pointer tables.
- */
- #include "ecah.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void ac_clear(void);
- /*--------------------------------------------------------------------------*/
- extern double *recon, *imcon; /* constant terms */
- extern double *reals, *imags; /* big array allocation bases */
- extern int decomp;
-
- extern const unsigned aspace; /* count of non-zero array elements */
- extern const struct status stats;
- /*--------------------------------------------------------------------------*/
- void ac_clear()
- {
- (void)memset((void*)reals, 0, (size_t)aspace * sizeof(double));
- (void)memset((void*)imags, 0, (size_t)aspace * sizeof(double));
- (void)memset((void*)recon, 0, (size_t)(stats.total_nodes+2)* sizeof(double));
- (void)memset((void*)imcon, 0, (size_t)(stats.total_nodes+2)* sizeof(double));
- decomp = 0;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_fill.c'
- then
- echo shar: will not over-write existing file "'src/ac_fill.c'"
- else
- cat << \SHAR_EOF > 'src/ac_fill.c'
- /* ac_fill 12/29/92
- * Copyright 1983-1992 Albert Davis
- * Fill working matrix for AC analysis
- */
- #include "ecah.h"
- #include "branch.h"
- #include "dev.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void ac_solve(void);
- void ac_fill_rl(branch_t*);
- /*--------------------------------------------------------------------------*/
- extern struct status stats;
- /*--------------------------------------------------------------------------*/
- void ac_solve()
- {
- ac_clear();
- time_start(&(stats.load));
- ac_fill_rl(firstbranch_dev());
- time_stop(&(stats.load));
- xsolve();
- }
- /*--------------------------------------------------------------------------*/
- void ac_fill_rl(brh)
- branch_t *brh;
- {
- branch_t *stop;
- if (exists(brh)){
- stop = brh;
- do {
- doac_branch(brh);
- } while (brh=nextbranch_dev(brh), brh != stop);
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_fix.c'
- then
- echo shar: will not over-write existing file "'src/ac_fix.c'"
- else
- cat << \SHAR_EOF > 'src/ac_fix.c'
- /* acfix 01/18/93
- * Copyright 1983-1992 Albert Davis
- * Takes care of nonlinearities, behavioral modeling, etc. in ac analysis.
- */
- #include "ecah.h"
- #include "ac.h"
- #include "branch.h"
- #include "error.h"
- #include "expr.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- complex_t acfix(branch_t*);
- static void acf_ac(const branch_t*,double**,int*,complex_t*);
- static void acf_dc(const branch_t*,double**,int*,complex_t*);
- static void acf_dctran(const branch_t*,double**,int*,complex_t*);
- static void acf_frequency(const branch_t*,double**,int*,complex_t*);
- static void acf_period(const branch_t*,double**,int*,complex_t*);
- static void acf_ramp(const branch_t*,double**,int*,complex_t*);
- static void acf_time(const branch_t*,double**,int*,complex_t*);
- static void acf_tran(const branch_t*,double**,int*,complex_t*);
- static void acf_bandwidth(const branch_t*,double**,complex_t*);
- static void acf_complex(const branch_t*,double**,complex_t*);
- static void acf_cornerdown(const branch_t*,double**,complex_t*);
- static void acf_cornerup(const branch_t*,double**,complex_t*);
- static void acf_delay(const branch_t*,double**,complex_t*);
- static void acf_exp(const branch_t*,double**,complex_t*);
- static void acf_expterm(const branch_t*,double**,complex_t*);
- static void acf_generator(const branch_t*,double**,complex_t*);
- static void acf_max(const branch_t*,double**,complex_t*);
- static void acf_netfunc(const branch_t*,double**,complex_t*);
- static void acf_notch(const branch_t*,double**,complex_t*);
- static void acf_numeric(const branch_t*,double**,complex_t*);
- static void acf_offset(const branch_t*,double**,complex_t*);
- static void acf_polar(const branch_t*,double**,complex_t*);
- static void acf_polyterm(const branch_t*,double**,complex_t*);
- static void acf_pulse(const branch_t*,double**,complex_t*);
- static void acf_pwl(const branch_t*,double**,complex_t*);
- static void acf_sffm(const branch_t*,double**,complex_t*);
- static void acf_sin(const branch_t*,double**,complex_t*);
- static void acf_tanh(const branch_t*,double**,complex_t*);
- static void acf_ic(const branch_t*,double**,complex_t*);
- static void acf_ii(const branch_t*,double**,complex_t*);
- static void acf_iv(const branch_t*,double**,complex_t*);
- static void acf_tempco(const branch_t*,double**,complex_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])
- #define xx0 (brh->acbias)
-
- extern const ac_t ac;
- extern const char e_int[]; /* error message */
- static int skip;
- /*--------------------------------------------------------------------------*/
- complex_t acfix(brh)
- branch_t *brh;
- {
- complex_t y; /* return value */
-
- skip = NO;
- y.x = brh->val;
- y.y = 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: acf_ac(brh,&arg,&skip,&y); break;
- case eDC: acf_dc(brh,&arg,&skip,&y); break;
- case eDCTRAN: acf_dctran(brh,&arg,&skip,&y); break;
- case eFREQUENCY: acf_frequency(brh,&arg,&skip,&y);break;
- case ePERIOD: acf_period(brh,&arg,&skip,&y); break;
- case eRAMP: acf_ramp(brh,&arg,&skip,&y); break;
- case eTIME: acf_time(brh,&arg,&skip,&y); break;
- case eTRAN: acf_tran(brh,&arg,&skip,&y); break;
-
- case eBANDWIDTH: acf_bandwidth(brh,&arg,&y); break;
- case eCOMPLEX: acf_complex(brh,&arg,&y); break;
- case eCORNERDOWN: acf_cornerdown(brh,&arg,&y); break;
- case eCORNERUP: acf_cornerup(brh,&arg,&y); break;
- case eDELAY: acf_delay(brh,&arg,&y); break;
- case eEXP: acf_exp(brh,&arg,&y); break;
- case eEXPTERM: acf_expterm(brh,&arg,&y); break;
- case eGENERATOR: acf_generator(brh,&arg,&y); break;
- case eMAX: acf_max(brh,&arg,&y); break;
- case eNETFUNC: acf_netfunc(brh,&arg,&y); break;
- case eNOTCH: acf_notch(brh,&arg,&y); break;
- case eNUMERIC: acf_numeric(brh,&arg,&y); break;
- case eOFFSET: acf_offset(brh,&arg,&y); break;
- case ePOLAR: acf_polar(brh,&arg,&y); break;
- case ePOLYTERM: acf_polyterm(brh,&arg,&y); break;
- case ePULSE: acf_pulse(brh,&arg,&y); break;
- case ePWL: acf_pwl(brh,&arg,&y); break;
- case eSFFM: acf_sffm(brh,&arg,&y); break;
- case eSIN: acf_sin(brh,&arg,&y); break;
- case eTANH: acf_tanh(brh,&arg,&y); break;
-
- case eIC: acf_ic(brh,&arg,&y); break;
- case eII: acf_ii(brh,&arg,&y); break;
- case eIV: acf_iv(brh,&arg,&y); break;
- case eTEMPCO: acf_tempco(brh,&arg,&y); break;
-
- default: error(bWARNING, "%s: undefined function: %d\n", printlabel(brh,NO), *key); break;
- }
- }
- }
- return y;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_ac: keyword: ac
- * following args for ac analysis only
- * here : do it
- */
- /*ARGSUSED*/
- static void acf_ac(brh,arg,skip,y) /* no args */
- const branch_t *brh;
- double **arg;
- int *skip;
- complex_t* y;
- {
- y->x = y->y = 0.;
- *skip = NO;
- *arg += aAC;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_dc: keyword: dc
- * following args for dc analysis only
- * here: skip them
- */
- /*ARGSUSED*/
- static void acf_dc(brh,arg,skip,y) /* no args */
- const branch_t *brh;
- double **arg;
- int *skip;
- complex_t *y;
- {
- *skip = YES;
- *arg += aDC;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_dctran: keyword: dctran
- * following args for dc and transient analysis
- * here: skip them
- */
- /*ARGSUSED*/
- static void acf_dctran(brh,arg,skip,y) /* no args */
- const branch_t *brh;
- double **arg;
- int *skip;
- complex_t* y;
- {
- *skip = YES;
- *arg += aDCTRAN;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_frequency: keyword: frequency
- * the value is frequency dependent (ac only)
- * works only in ac analysis, otherwise could be non-causal.
- */
- /*ARGSUSED*/
- static void acf_frequency(brh,arg,skip,y) /* arg0 = test freq */
- const branch_t *brh;
- double **arg;
- int *skip;
- complex_t *y;
- {
- error(bWARNING,"frequency not implemented: %s\n", printlabel(brh,NO));
- *arg += aFREQUENCY;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_period: keyword: period
- * periodic in time
- * implies that following args for transient analysis only.
- * here: skip them
- */
- /*ARGSUSED*/
- static void acf_period(brh,arg,skip,y) /* arg0 = period */
- const branch_t *brh;
- double **arg;
- int *skip;
- complex_t *y;
- {
- *skip = YES;
- *arg += aPERIOD;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_ramp: keyword: ramp
- * ramp value between plotted points
- * transient only: skip here
- */
- /*ARGSUSED*/
- static void acf_ramp(brh,arg,skip,y)
- const branch_t *brh;
- double **arg;
- int *skip;
- complex_t *y;
- {
- *skip = YES;
- *arg += aRAMP;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_time: keyword: time
- * following args take effect at the given time (switch)
- * obviously, transient only.
- */
- /*ARGSUSED*/
- static void acf_time(brh,arg,skip,y) /* arg0 = switch time */
- const branch_t *brh;
- double **arg;
- int *skip;
- complex_t *y;
- {
- *skip = YES;
- *arg += aTIME;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_tran: keyword: transient
- * following args for transient analysis only.
- */
- /*ARGSUSED*/
- static void acf_tran(brh,arg,skip,y) /* no args */
- const branch_t *brh;
- double **arg;
- int *skip;
- complex_t *y;
- {
- *skip = YES;
- *arg += aTRAN;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_bandwidth: function: bandwidth
- * gain block, with a bandwidth. (ac only)
- * bad design: should be keyword instead.
- */
- /*ARGSUSED*/
- static void acf_bandwidth(brh,arg,y) /* arg0 = dc gain */
- const branch_t *brh; /* arg1 = 3 db freq. */
- double **arg;
- complex_t *y;
- {
- if (!skip && arg1 != 0.){
- double ratio;
- double coeff;
- ratio = ac.freq / arg1;
- coeff = arg0 / (1.+(ratio*ratio));
- y->x += coeff;
- y->y -= coeff * ratio;
- }
- *arg += aBANDWIDTH;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_complex: function: complex
- * complex value, cartesian coordinates, in frequency domain (ac only)
- */
- /*ARGSUSED*/
- static void acf_complex(brh,arg,y) /* arg0 = real part */
- const branch_t *brh; /* arg1 = imaginary part */
- double **arg;
- complex_t *y;
- {
- if (!skip){
- y->x += arg0;
- y->y += arg1;
- }
- *arg += aCOMPLEX;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_cornerdown: function: cornerdown
- * piecewise linear function:
- * output is 0 for bias >= arg1
- * derivative is arg0 for bias <= arg1
- */
- static void acf_cornerdown(brh,arg,y) /* arg0 = active slope */
- const branch_t *brh; /* arg1 = break point */
- double **arg;
- complex_t *y;
- {
- if (!skip && xx0 < arg1)
- y->x += arg0;
- *arg += aCORNERDOWN;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_cornerup: function: cornerup
- * piecewise linear function:
- * output is 0 for bias <= arg1
- * derivative is arg0 for bias >= arg1
- */
- static void acf_cornerup(brh,arg,y) /* arg0 = active slope */
- const branch_t *brh; /* arg1 = break point */
- double **arg;
- complex_t *y;
- {
- if (!skip && xx0 > arg1)
- y->x += arg0;
- *arg += aCORNERUP;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_delay: function: delay
- * time delay (ac only)
- */
- static void acf_delay(brh,arg,y) /* arg0 = magnitude */
- const branch_t *brh; /* arg1 = delay */
- double **arg;
- complex_t *y;
- {
- if (!skip){
- double ratio;
- double dphase;
- ratio = ac.freq * arg1;
- if (ratio > 100000.){
- error(bPICKY, "delay too long: %s\n", printlabel(brh,NO));
- ratio = 0.;
- }
- dphase = -360.0 * ratio;
- y->x += real(arg0, dphase);
- y->y += imag(arg0, dphase);
- }
- *arg += aDELAY;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_exp: spice compatible function: exp
- * spice source exponential function: exponential function of time
- * no-op in ac analysis, with a complaint
- */
- /*ARGSUSED*/
- static void acf_exp(brh,arg,y) /* arg0 = initial value */
- const branch_t *brh; /* arg1 = pulsed value */
- double **arg; /* arg2 = rise delay */
- complex_t *y; /* arg3 = rise time const */
- { /* arg4 = fall delay */
- /* arg5 = fall time const */
- if (!skip)
- error(bDEBUG,"%s: exp not supported in ac analysis\n",printlabel(brh,NO));
- *arg += aEXP;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_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 acf_expterm(brh,arg,y) /* arg0 = coefficient */
- const branch_t *brh; /* arg1 = exponent */
- double **arg;
- complex_t *y;
- {
- if (!skip && xx0 > 0.){
- double coeff;
- coeff = arg0 * pow(xx0,arg1-1);
- y->x += coeff * arg1;
- }
- *arg += aEXPTERM;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_generator: function: generator
- * value is derived from the "signal generator" (generator command)
- * intended for fixed sources, as circuit input.
- */
- /*ARGSUSED*/
- static void acf_generator(brh,arg,y) /* arg0 = scale factor */
- const branch_t *brh;
- double **arg;
- complex_t *y;
- {
- if (!skip){
- y->x += arg0;
- /* y->y += 0.; */
- }
- *arg += aGENERATOR;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_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 acf_max(brh,arg,y) /* arg0 = normal value */
- const branch_t *brh; /* arg1 = output clip pt */
- double **arg;
- complex_t *y;
- {
- if (!skip && arg0 != 0.){
- double clip_input;
- clip_input = arg1/arg0;
- if (xx0 >= -clip_input && xx0 <= clip_input)
- y->x += arg0;
- }
- *arg += aMAX;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_netfunc: function: netfunction
- * gain block, nth order response. (ac only)
- * BUG: only partial checking for number of args
- */
- /*ARGSUSED*/ /* arg0 = arg count */
- static void acf_netfunc(brh,arg,y) /* arg1 = dc gain */
- const branch_t *brh; /* arg2 = ref frequency */
- double **arg; /* arg3 = order of denom*/
- complex_t *y; /* arg* = coefs of denom*/
- { /* arg* = coefs of numer*/
- int argcount;
- argcount = (int)arg0;
-
- if (!skip && arg1 != 0.){
- double *denomcoeff; /* coefficients of denominator */
- double *numercoeff; /* coefficients of numerator */
- int denomorder; /* order of denominator (#coefs = order + 1) */
- int numerorder; /* order of numerator */
- double wacc; /* stash for powers of f */
- complex_t denom; /* denominator */
- complex_t numer; /* numerator */
- complex_t result; /* result of evaluating the function */
- int ii; /* generic loop index */
- double normfreq; /* normalized frequency */
- double nf2; /* " " squared */
-
- normfreq = ac.freq / ((arg2 != 0.) ? arg2 : 1./PI2);
- nf2 = normfreq * normfreq;
-
- denomorder = (int)arg3;
- numerorder = argcount - denomorder - 6;
- if (numerorder > denomorder){
- numerorder = denomorder;
- error(bWARNING, "%s: too many args\n", printlabel(brh,NO));
- }else if (numerorder < 0){
- denomorder += numerorder;
- numerorder = 0;
- error(bWARNING, "%s: too few args\n", printlabel(brh,NO));
- }
-
- denomcoeff = &(arg[0][4]);
- numercoeff = &(arg[0][5+denomorder]);
-
- wacc = 1.;
- denom.x = denomcoeff[0]; /* * wacc */
- for (ii = 2; ii <= denomorder; ii += 2){
- wacc *= -nf2;
- denom.x += denomcoeff[ii] * wacc;
- }
-
- wacc = normfreq;
- denom.y = denomcoeff[1] * wacc;
- for (ii = 3; ii <= denomorder; ii += 2){
- wacc *= -nf2;
- denom.y += denomcoeff[ii] * wacc;
- }
-
- wacc = 1.;
- numer.x = numercoeff[0]; /* * wacc */
- for (ii = 2; ii <= numerorder; ii += 2){
- wacc *= -nf2;
- numer.x += numercoeff[ii] * wacc;
- }
-
- wacc = normfreq;
- numer.y = numercoeff[1] * wacc;
- for (ii = 3; ii <= numerorder; ii += 2){
- wacc *= -nf2;
- numer.y += numercoeff[ii] * wacc;
- }
-
- result = cdiv(numer, denom);
- y->x += result.x * arg1;
- y->y += result.y * arg1;
- }
- *arg += argcount;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_notch: function: notch
- * piecewise linear function: crossover notch, dead zone
- * symmetric around zero
- */
- static void acf_notch(brh,arg,y) /* arg0 = normal value */
- const branch_t *brh; /* arg1 = dead zone size */
- double **arg;
- complex_t *y;
- {
- if (!skip){
- if (xx0 > arg1 || xx0 < -arg1)
- y->x += arg0;
- }
- *arg += aNOTCH;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_numeric: simple numeric argument
- */
- /*ARGSUSED*/
- static void acf_numeric(brh,arg,y) /* arg0 = value */
- const branch_t *brh;
- double **arg;
- complex_t *y;
- {
- if (!skip)
- y->x += arg0;
- *arg += aNUMERIC;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_offset: function: offset
- * fixed dc offset
- * bad design: should be keyword
- */
- /*ARGSUSED*/
- static void acf_offset(brh,arg,y) /* arg0 = gain */
- const branch_t *brh; /* arg1 = output offset */
- double **arg;
- complex_t *y;
- {
- if (!skip)
- y->x += arg0;
- *arg += aOFFSET;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_polar: function: polar
- * complex value in polar coordinates, in frequency domain (ac only)
- */
- /*ARGSUSED*/
- static void acf_polar(brh,arg,y) /* arg0 = magnitude */
- const branch_t *brh; /* arg1 = phase */
- double **arg;
- complex_t *y;
- {
- if (!skip){
- y->x += real(arg0, arg1);
- y->y += imag(arg0, arg1);
- }
- *arg += aPOLAR;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_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 acf_polyterm(brh,arg,y) /* arg0 = coefficient */
- const branch_t *brh; /* arg1 = exponent */
- double **arg;
- complex_t *y;
- {
- if (!skip){
- int expo;
- expo = (int)floor(arg1+.5);
- if (expo != 0){
- double coeff;
- coeff = arg0 * ipow(xx0,expo-1);
- y->x += coeff * expo;
- }
- }
- *arg += aPOLYTERM;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_pulse: spice compatible function: pulse
- * spice pulse function (for sources)
- * no-op in ac analysis, with a complaint
- */
- /*ARGSUSED*/
- static void acf_pulse(brh,arg,y) /* arg0 = initial value */
- const branch_t *brh; /* arg1 = pulsed value */
- double **arg; /* arg2 = delay time */
- complex_t *y; /* arg3 = rise time */
- { /* arg4 = fall time */
- /* arg5 = pulse width */
- if (!skip) /* arg6 = period */
- error(bDEBUG,"%s: pulse not supported in ac analysis\n",printlabel(brh,NO));
- *arg += aPULSE;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_pwl: spice compatible function: pwl
- * "piece-wise linear" point-plotting function of time.
- * no-op in ac analysis, with a complaint
- */
- /*ARGSUSED*/
- static void acf_pwl(brh,arg,y) /* arg0 = time */
- const branch_t *brh; /* arg1 = value */
- double **arg; /* etc. */
- complex_t *y;
- {
- if (!skip)
- error(bDEBUG,"%s: pwl not supported in ac analysis\n",printlabel(brh,NO));
-
- if (aPWL == aVARIABLE){
- *arg += (int)(**arg);
- }else{
- *arg += aPWL;
- error(bWARNING, e_int, "acf_pwl");
- }
- }
- /*--------------------------------------------------------------------------*/
- /* acf_sffm: spice compatible function: sffm
- * single frequency frequency modulation
- * no-op in ac analysis, with a complaint
- */
- /*ARGSUSED*/
- static void acf_sffm(brh,arg,y) /* arg0 = dc offset */
- const branch_t *brh; /* arg1 = amplitude */
- double **arg; /* arg2 = carrier freq */
- complex_t *y; /* arg3 = mod index */
- { /* arg4 = signal freq */
- if (!skip)
- error(bDEBUG,"%s: sffm not supported in ac analysis\n",printlabel(brh,NO));
- *arg += aSFFM;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_sin: spice compatible function: sin
- * sinusoidal function, mainly for sources
- * no-op in ac analysis, with a complaint
- */
- /*ARGSUSED*/
- static void acf_sin(brh,arg,y) /* arg0 = offset */
- const branch_t *brh; /* arg1 = amplitude */
- double **arg; /* arg2 = frequency */
- complex_t *y; /* arg3 = delay */
- { /* arg4 = damping */
- if (!skip)
- error(bDEBUG,"%s: sin not supported in ac analysis\n",printlabel(brh,NO));
- *arg += aSIN;
- }
- /*--------------------------------------------------------------------------*/
- /* acf_tanh: function: tanh
- * for now, a copy of 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 acf_tanh(brh,arg,y) /* arg0 = normal value */
- const branch_t *brh; /* arg1 = output clip pt */
- double **arg;
- complex_t *y;
- {
- if (!skip){
- if (arg1 != 0.){
- double cosine;
- cosine = cosh(xx0 * arg0/arg1);
- y->x += arg0 / (cosine*cosine);
- }
- /* else 0 */
- }
- *arg += aTANH;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void acf_ic(brh,arg,y)
- const branch_t *brh;
- double **arg;
- complex_t *y;
- {
- *arg += 1;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void acf_ii(brh,arg,y)
- const branch_t *brh;
- double **arg;
- complex_t *y;
- {
- *arg += 1;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void acf_iv(brh,arg,y)
- const branch_t *brh;
- double **arg;
- complex_t *y;
- {
- *arg += 1;
- }
- /*--------------------------------------------------------------------------*/
- /*ARGSUSED*/
- static void acf_tempco(brh,arg,y)
- const branch_t *brh;
- double **arg;
- complex_t *y;
- {
- #ifdef NEVER
- tempco = arg0;
- #endif
- *arg += 1;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_load.c'
- then
- echo shar: will not over-write existing file "'src/ac_load.c'"
- else
- cat << \SHAR_EOF > 'src/ac_load.c'
- /* ac_load 04/02/92
- * Copyright 1983-1992 Albert Davis
- * Load AC matrix from pre-computed values
- */
- #include "ecah.h"
- #include "array.h"
- #include "branch.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void acloadsource(const branch_t*);
- void acloadpassive(const branch_t*);
- void acloadpassivereal(const branch_t*);
- void acloadpassiveimaginary(const branch_t*);
- void acloadactive(const branch_t*);
- /*--------------------------------------------------------------------------*/
- extern double *recon, *imcon; /* right side vector, 2 = complex */
- /*--------------------------------------------------------------------------*/
- void acloadsource(brh)
- const branch_t *brh;
- {
- if (brh->n[OUT2].m != 0){
- recon[brh->n[OUT2].m] += brh->acg.x;
- imcon[brh->n[OUT2].m] += brh->acg.y;
- }
- if (brh->n[OUT1].m != 0){
- recon[brh->n[OUT1].m] -= brh->acg.x;
- imcon[brh->n[OUT1].m] -= brh->acg.y;
- }
- }
- /*--------------------------------------------------------------------------*/
- void acloadpassive(brh)
- const branch_t *brh;
- {
- if (brh->acg.x != 0.)
- acloadpassivereal(brh);
- if (brh->acg.y != 0.)
- acloadpassiveimaginary(brh);
- }
- /*--------------------------------------------------------------------------*/
- void acloadpassivereal(brh)
- const branch_t *brh;
- {
- if (brh->n[OUT2].m != 0){
- *Red(brh->n[OUT2].m,brh->n[OUT2].m) += brh->acg.x;
- if (brh->n[OUT1].m != 0){
- *Red(brh->n[OUT1].m,brh->n[OUT1].m) += brh->acg.x;
- *Re(brh->n[OUT1].m,brh->n[OUT2].m) -= brh->acg.x;
- *Re(brh->n[OUT2].m,brh->n[OUT1].m) -= brh->acg.x;
- }
- }else if (brh->n[OUT1].m != 0){
- *Red(brh->n[OUT1].m,brh->n[OUT1].m) += brh->acg.x;
- }
- }
- /*--------------------------------------------------------------------------*/
- void acloadpassiveimaginary(brh)
- const branch_t *brh;
- {
- if (brh->n[OUT2].m != 0){
- *Imd(brh->n[OUT2].m,brh->n[OUT2].m) += brh->acg.y;
- if (brh->n[OUT1].m != 0){
- *Imd(brh->n[OUT1].m,brh->n[OUT1].m) += brh->acg.y;
- *Im(brh->n[OUT1].m,brh->n[OUT2].m) -= brh->acg.y;
- *Im(brh->n[OUT2].m,brh->n[OUT1].m) -= brh->acg.y;
- }
- }else if (brh->n[OUT1].m != 0){
- *Imd(brh->n[OUT1].m,brh->n[OUT1].m) += brh->acg.y;
- }
- }
- /*--------------------------------------------------------------------------*/
- void acloadactive(brh)
- const branch_t *brh;
- {
- if (brh->acg.x != 0.){
- *re(brh->n[OUT1].m,brh->n[IN1].m) += brh->acg.x;
- *re(brh->n[OUT2].m,brh->n[IN2].m) += brh->acg.x;
- *re(brh->n[OUT1].m,brh->n[IN2].m) -= brh->acg.x;
- *re(brh->n[OUT2].m,brh->n[IN1].m) -= brh->acg.x;
- }
- if (brh->acg.y != 0.){
- *im(brh->n[OUT1].m,brh->n[IN1].m) += brh->acg.y;
- *im(brh->n[OUT2].m,brh->n[IN2].m) += brh->acg.y;
- *im(brh->n[OUT1].m,brh->n[IN2].m) -= brh->acg.y;
- *im(brh->n[OUT2].m,brh->n[IN1].m) -= brh->acg.y;
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_out.c'
- then
- echo shar: will not over-write existing file "'src/ac_out.c'"
- else
- cat << \SHAR_EOF > 'src/ac_out.c'
- /* ac_out 01/26/93
- * Copyright 1983-1992 Albert Davis
- * ac analysis output functions
- */
- #include "ecah.h"
- #include "ac.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 ac_out(const ac_t*);
- static void ac_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 */
- /*--------------------------------------------------------------------------*/
- void ac_out(ac)
- const ac_t *ac;
- {
- time_start(&(stats.output));
- plotac(ac->freq);
- ac_print(ac->freq);
- time_stop(&(stats.output));
- }
- /*--------------------------------------------------------------------------*/
- /* ac_print: print the list of results (text form) to io.where
- * The argument is the first column (independent variable, aka "x")
- */
- static void ac_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 = acprobe(prb);
- mprintf(io.where,ftos(value," ",5,io.formaat));
- }
- }
- mprintf(io.where,"\n");
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_probe.c'
- then
- echo shar: will not over-write existing file "'src/ac_probe.c'"
- else
- cat << \SHAR_EOF > 'src/ac_probe.c'
- /* acprobe 01/11/93
- * Copyright 1983-1992 Albert Davis
- * collection of probe functions for ac analysis
- */
- #include "ecah.h"
- #include "branch.h"
- #include "error.h"
- #include "probh.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- double acprobe(probe_t);
- static double acprobe_node(probe_t);
- /*--------------------------------------------------------------------------*/
- extern const struct status stats;
- extern const double temp;
- extern const double trtime;
- extern const double *recon; /* constant vector, real part */
- extern const double *imcon; /* constant vector, imaginary part */
- extern const int *nm; /* node map (map internal to user nodes) */
- /*--------------------------------------------------------------------------*/
- double acprobe(prb)
- probe_t prb;
- {
- if (prb.p.node <= stats.total_nodes){
- return acprobe_node(prb);
- }else{
- return acprobe_branch(prb.p.brh,prb.what);
- }
- }
- /*--------------------------------------------------------------------------*/
- static double acprobe_node(prb)
- probe_t prb;
- {
- int dummy = 0;
-
- setmatch(prb.what,&dummy);
- 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") || rematch("VM")){
- return hypot(recon[nm[prb.p.node]],imcon[nm[prb.p.node]]);
- }else if (rematch("VDB")){
- double v = hypot(recon[nm[prb.p.node]],imcon[nm[prb.p.node]]);
- return (v > VMIN) ? 20. * log10(v) : DBVMIN;
- }else if (rematch("VP")){
- return phase(recon[nm[prb.p.node]],imcon[nm[prb.p.node]]);
- }else{ /* bad parameter */
- return NOT_VALID;
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_setup.c'
- then
- echo shar: will not over-write existing file "'src/ac_setup.c'"
- else
- cat << \SHAR_EOF > 'src/ac_setup.c'
- /* ac_setup 12/31/92
- * Copyright 1983-1992 Albert Davis
- * ac analysis setup
- */
- #include "ecah.h"
- #include "ac.h"
- #include "argparse.h"
- #include "error.h"
- #include "io.h"
- #include "mode.h"
- #include "options.h"
- #include "worst.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void ac_setup(const char*,int*,ac_t*);
- static void ac_optby(const char*,int*);
- static void ac_optdecade(const char*,int*);
- static void ac_optlin(const char*,int*);
- static void ac_optoctave(const char*,int*);
- static void ac_opttimes(const char*,int*);
- /*--------------------------------------------------------------------------*/
- extern struct ioctrl io;
- extern const struct options opt;
- extern int worstcase; /* worst case, monte carlo mode (enum type, worst.h)*/
- extern double temp; /* actual ambient temperature, kelvin */
- static int needslinfix; /* flag: lin option needs patch later (spice compat)*/
- static ac_t *ac;
- /*--------------------------------------------------------------------------*/
- void ac_setup(cmd,cnt,params)
- const char *cmd;
- int *cnt;
- ac_t *params;
- {
- ac = params;
- io.where |= io.mstdout;
- temp = opt.tempamb;
- io.ploton = io.plotset;
- ac->echo = worstcase = NO;
- for (;;){
- if (argparse(cmd,cnt,REPEAT,
- "*", aFUNCTION, ac_opttimes,
- "ACMAx", aENUM, &worstcase, wMAXAC,
- "ACMIn", aENUM, &worstcase, wMINAC,
- "Ambient", aODOUBLE, &temp, opt.tempamb,
- "By", aFUNCTION, ac_optby,
- "DCMAx", aENUM, &worstcase, wMAXDC,
- "DCMIn", aENUM, &worstcase, wMINDC,
- "Decade", aFUNCTION, ac_optdecade,
- "Echo", aENUM, &ac->echo, YES,
- "LAg", aENUM, &worstcase, wLAG,
- "LEad", aENUM, &worstcase, wLEAD,
- "LIn", aFUNCTION, ac_optlin,
- "MAx", aENUM, &worstcase, wMAXAC,
- "MIn", aENUM, &worstcase, wMINAC,
- "NOPlot", aENUM, &io.ploton, NO,
- "Octave", aFUNCTION, ac_optoctave,
- "PLot", aENUM, &io.ploton, YES,
- "Reftemp", aODOUBLE, &temp, opt.tnom,
- "SEnsitivity", aENUM, &worstcase, wSENS,
- "Temperature", aODOUBLE, &temp, -ABS_ZERO,
- "TImes", aFUNCTION, ac_opttimes,
- ""))
- ;
- else if (isfloat(cmd[*cnt])){
- ac->start = ctof(cmd,cnt);
- ac->stop = ctof(cmd,cnt);
- if (ac->stop==0.)
- ac->stop = ac->start;
- if (isfloat(cmd[*cnt]))
- ac_optby(cmd,cnt);
- }else if (outset(cmd,cnt,(char*)NULL,"ac ")){
- ;
- }else{
- syntax(cmd,cnt,bWARNING);
- break;
- }
- }
- initio(io.where,io.whence);
- if (worstcase==wRAND || worstcase==wWORST)
- io.ploton = NO;
- if (needslinfix){ /* LIN option is # of steps. */
- ac->step=(ac->stop-ac->start)/ac->step;/* Must compute ac->step after */
- needslinfix = NO; /* reading start and stop, */
- } /* but step must be read first */
- if (ac->step==0.){ /* for Spice compatibility */
- ac->step = ac->stop - ac->start;
- ac->linswp = YES;
- }
- }
- /*--------------------------------------------------------------------------*/
- static void ac_optby(cmd,cnt)
- const char *cmd;
- int *cnt;
- {
- ac->step = ctof(cmd,cnt);
- needslinfix = NO;
- ac->linswp = YES;
- }
- /*--------------------------------------------------------------------------*/
- static void ac_optdecade(cmd,cnt)
- const char *cmd;
- int *cnt;
- {
- ac->step = fabs(ctof(cmd,cnt));
- if (ac->step == 0.)
- ac->step = 1.;
- ac->step = pow(10., 1./ac->step);
- needslinfix = NO;
- ac->linswp = NO;
- }
- /*--------------------------------------------------------------------------*/
- static void ac_optlin(cmd,cnt)
- const char *cmd;
- int *cnt;
- {
- ac->step = fabs(ctof(cmd,cnt)); /* need to fix ac->step, later */
- if (ac->step == 0.) /* do it at the end of ac_setup */
- ac->step = 1.; /* a kluge, but this is a patch */
- needslinfix = YES; /* and I am too lazy to do it */
- ac->linswp = YES; /* right. */
- }
- /*--------------------------------------------------------------------------*/
- static void ac_optoctave(cmd,cnt)
- const char *cmd;
- int *cnt;
- {
- ac->step = fabs(ctof(cmd,cnt));
- if (ac->step == 0.)
- ac->step = 1.;
- ac->step = pow(2.00000001, 1./ac->step);
- needslinfix = NO;
- ac->linswp = NO;
- }
- /*--------------------------------------------------------------------------*/
- static void ac_opttimes(cmd,cnt)
- const char *cmd;
- int *cnt;
- {
- ac->step = fabs(ctof(cmd,cnt));
- if (ac->step == 0. && ac->start != 0.)
- ac->step = ac->stop / ac->start;
- needslinfix = NO;
- ac->linswp = NO;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_sweep.c'
- then
- echo shar: will not over-write existing file "'src/ac_sweep.c'"
- else
- cat << \SHAR_EOF > 'src/ac_sweep.c'
- /* ac_sweep 01/26/93
- * Copyright 1983-1992 Albert Davis
- * ac analysis sweep
- */
- #include "ecah.h"
- #include "ac.h"
- #include "io.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void ac_sweep(ac_t*);
- static void ac_first(ac_t*);
- static int ac_next(ac_t*);
- /*--------------------------------------------------------------------------*/
- extern const struct ioctrl io;
- /*--------------------------------------------------------------------------*/
- void ac_sweep(ac)
- ac_t *ac;
- {
- tr_head(ac->start, ac->stop, ac->linswp, "Freq");
- ac_first(ac);
- do {
- ac_solve();
- ac_out(ac);
- } while (ac_next(ac));
- }
- /*--------------------------------------------------------------------------*/
- static void ac_first(ac)
- ac_t *ac;
- {
- ac->freq = ac->start;
- ac->omega = ac->freq * PI2;
- }
- /*--------------------------------------------------------------------------*/
- static int ac_next(ac)
- ac_t *ac;
- {
- double stop;
-
- if (io.whence)
- return YES;
- stop = (ac->linswp)
- ? ac->stop - ac->step/100.
- : ac->stop / pow(ac->step,.01);
- if (!inorder(ac->start, ac->freq, stop))
- return NO;
- ac->freq = (ac->linswp)
- ? ac->freq + ac->step
- : ac->freq * ac->step;
- ac->omega = ac->freq * PI2;
- if (inorder(ac->freq, ac->start, ac->stop))
- return NO;
- return YES;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/ac_z.c'
- then
- echo shar: will not over-write existing file "'src/ac_z.c'"
- else
- cat << \SHAR_EOF > 'src/ac_z.c'
- /* acz 01/11/93
- * Copyright 1983-1992 Albert Davis
- * impedance at a port
- */
- #include "ecah.h"
- #include "error.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- complex_t acz(int,int,complex_t);
- /*--------------------------------------------------------------------------*/
- extern const struct status stats;
- extern const char e_om[];
-
- extern double *recon;
- extern double *imcon;
- /*--------------------------------------------------------------------------*/
- complex_t acz(n1,n2,parallel)
- int n1,n2; /* node pair */
- complex_t parallel; /* parallel admittance to remove */
- {
- static double *rezap, *imzap;
- static unsigned gotsize;
- unsigned newsize;
- double *resave, *imsave; /* temporary storage: normal right side */
- complex_t raw_z; /* raw impedance (includes par branch) */
-
- newsize = ((unsigned)stats.total_nodes+2) * sizeof(double);
- if (!rezap || !imzap){
- rezap = (double*)calloc(newsize,1);
- imzap = (double*)calloc(newsize,1);
- gotsize = newsize;
- }else if (newsize > gotsize){
- rezap = (double*)realloc((void*)rezap,newsize);
- imzap = (double*)realloc((void*)imzap,newsize);
- gotsize = newsize;
- }
- if (!rezap || !imzap)
- error(bERROR, e_om, "acz");
-
- resave = recon;
- imsave = imcon;
-
- (void)memset((void*)recon,0,newsize);
- (void)memset((void*)imcon,0,newsize);
- if (n1)
- recon[n1] = 1.;
- if (n2)
- recon[n2] = -1.;
-
- xsolve();
- raw_z.x = recon[n1] - recon[n2];
- raw_z.y = imcon[n1] - imcon[n2];
-
- recon = resave;
- imcon = imsave;
-
- /* return ckt_z */
- /* return 1 / ((1/raw_z) - parallel) */
- return cflip(csub(cflip(raw_z),parallel));
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/allocate.c'
- then
- echo shar: will not over-write existing file "'src/allocate.c'"
- else
- cat << \SHAR_EOF > 'src/allocate.c'
- /* allocate 01/11/93
- * Copyright 1983-1992 Albert Davis
- * Allocates space for the admittance matrix. Allocation below the
- * diagonal is by row, above the diagonal is by column, and stored backwards.
- * This broken vector is stored. The length of it increases with increasing
- * position. The maximum length of the nth vector is 2n-1. For a band matrix
- * only those elements that are non-zero or are nearer to the diagonal than a
- * non-zero element are stored.
- */
- #include "ecah.h"
- #include "branch.h"
- #include "dev.h"
- #include "error.h"
- #include "mode.h"
- #include "nodestat.h"
- #include "options.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- void allocate(int);
- static void count_nodes(void);
- static void expand_list(branch_t*);
- static void map_nodes(void);
- static void order_reverse(void);
- static void order_forward(void);
- static void order_auto(void);
- static void map_list(branch_t*);
- static void build_basenode_table(void);
- static void addto_basenode_table(const branch_t*);
- static void lownode(int,int);
- static void alloc_hold_vectors(void);
- static unsigned size_arrays(void);
- static void alloc_matrix(int,unsigned);
- static void alloc_constants(int);
- static void alloc_pointer_table(int);
- static void fill_pointer_table(int);
- /*--------------------------------------------------------------------------*/
- extern const struct options opt;
- extern struct status stats;
-
- extern const char e_om[];
-
- extern int decomp; /* how far the array been decomposed */
- extern int *basnode; /* lowest node connected to this node */
- extern int *nm; /* node map table */
- extern unsigned aspace; /* count of non-zero array elements */
- extern double **rerow, **imrow; /* array of row pointers */
- extern double **recol, **imcol; /* array of column pointers */
- extern double **redia, **imdia; /* array of diagonal pointers */
- extern double *recon,*imcon,*oldcon,*fwcon;/* constant terms */
- extern double *reals, *imags; /* big array allocation bases */
- extern struct nodestat *nstat; /* node status flags */
- extern double *volts;
- /*--------------------------------------------------------------------------*/
- /* allocate: memory allocation for simulation
- */
- void allocate(mode)
- int mode;
- {
- decomp = 0; /* start decomposition over */
-
- if (mode != sSTATUS){
- time_reset(&(stats.load));
- time_reset(&(stats.lu));
- time_reset(&(stats.back));
- time_reset(&(stats.review));
- time_reset(&(stats.output));
-
- time_zstart(&(stats.setup));
- }
- if (!volts){ /* if "volts" not allocated, */
- dealloc(YES); /* must allocate everything */
- count_nodes(); /* and start solution over. */
- expand_list(firstbranch_dev());
- map_nodes();
- build_basenode_table();
- alloc_hold_vectors();
- aspace = size_arrays();
- if (mode==sSTATUS)
- dealloc(YES);
- }
- if (mode==sSTATUS)
- return; /* done if status */
- if (!exists(firstbranch_all()))
- error(bERROR, "no circuit\n");
-
- /* lost between commands. re-- every time */
- alloc_matrix(mode,aspace);
- alloc_constants(mode);
- alloc_pointer_table(mode);
- fill_pointer_table(mode);
- if (mode != sSTATUS)
- time_stop(&(stats.setup));
- }
- /*--------------------------------------------------------------------------*/
- /* count_nodes: count nodes in main ckt (not subckts)
- * update the variables "stats.total_nodes" and "stats.user_nodes"
- * zeros "stats.subckt_nodes" and "stats.model_nodes"
- */
- static void count_nodes()
- {
- const branch_t *stop;
-
- stats.user_nodes = 0;
- stop = firstbranch_dev();
- if (isdevice(stop)){
- const branch_t *brh;
- brh = stop;
- do {
- int ii;
- for (ii = 0; brh->n[ii].e != INVALIDNODE; ii++){
- if (brh->n[ii].e > stats.user_nodes)
- stats.user_nodes = brh->n[ii].e;
- }
- } while (brh = nextbranch_dev(brh), brh != stop);
- }
- stats.total_nodes = stats.user_nodes;
- stats.subckt_nodes = stats.model_nodes = 0;
- }
- /*--------------------------------------------------------------------------*/
- /* expand_list: expand (flatten) a list of components (subckts)
- * Scan component list. Expand each subckt: create actual elements
- * for flat representation to use for simulation.
- * Recursive to allow for nested subckts.
- */
- static void expand_list(stop)
- branch_t *stop;
- {
- if (isdevice(stop)){
- branch_t *brh;
- brh = stop;
- do {
- expand_branch(brh);
- if (brh->subckt){
- expand_list(brh->subckt);
- }
- } while (brh=nextbranch_dev(brh), brh != stop);
- }
- }
- /*--------------------------------------------------------------------------*/
- /* map_nodes: map intermediate node number to internal node number.
- * Ideally, this function would find some near-optimal order
- * and squash out gaps.
- */
- static void map_nodes()
- {
- nm = (int*)calloc((unsigned)stats.total_nodes+1, sizeof(int));
- if (!nm) /* node map table */
- error(bERROR, e_om, "nm");
- time_zstart(&(stats.order));
- switch (opt.order){
- default:
- error(bWARNING, "invalid order spec: %d\n", opt.order);
- /* fall through to order_reverse. */
- case oAUTO:
- order_auto();
- break;
- case oREVERSE:
- order_reverse();
- break;
- case oFORWARD:
- order_forward();
- break;
- }
- time_stop(&(stats.order));
- map_list(firstbranch_dev());
- }
- /*--------------------------------------------------------------------------*/
- /* order_reverse: force ordering to reverse of user ordering
- * subcircuits at beginning, results on border at the bottom
- */
- static void order_reverse()
- {
- int node;
- nm[0] = 0;
- for (node=1; node<=stats.total_nodes; ++node)
- nm[node] = stats.total_nodes - node + 1;
- }
- /*--------------------------------------------------------------------------*/
- /* order_forward: use user ordering, with subcircuits added to end
- * results in border at the top (worst possible if lots of subcircuits)
- */
- static void order_forward()
- {
- int node;
- nm[0] = 0;
- for (node=1; node<=stats.total_nodes; ++node)
- nm[node] = node;
- }
- /*--------------------------------------------------------------------------*/
- /* order_auto: full automatic ordering
- * reverse, for now
- */
- static void order_auto()
- {
- int node;
- nm[0] = 0;
- for (node=1; node<=stats.total_nodes; ++node)
- nm[node] = stats.total_nodes - node + 1;
- }
- /*--------------------------------------------------------------------------*/
- /* map_list: map intermediate node to internal (working) node number.
- * recursive: actual mapping done here
- */
- static void map_list(stop)
- branch_t *stop;
- {
- if (isdevice(stop)){
- branch_t *brh;
- brh = stop;
- do {
- int ii;
- for (ii = 0; brh->n[ii].t != INVALIDNODE; ii++){
- brh->n[ii].m = nm[brh->n[ii].t];
- }
- brh->n[ii].m = INVALIDNODE;
- if (brh->subckt)
- map_list(brh->subckt);
- } while (brh = nextbranch_dev(brh), brh != stop);
- }
- }
- /*--------------------------------------------------------------------------*/
- /* build_basenode_table: build a table containing the lowest node number
- * connected to each node. This determines the bandwidth of the matrix,
- * or the length of the vectors (in the matrix) corresponding to each node.
- * Actual work is done by addto_basenode_table.
- */
- static void build_basenode_table()
- {
- int node;
-
- basnode = (int*)calloc((unsigned)stats.total_nodes+1, sizeof(int));
- if (!basnode) /* base-node, (vector size) table */
- error(bERROR, e_om, "basnode");
-
- for (node = 0; node <= stats.total_nodes; ++node)
- basnode[node] = node; /* initialize each to itself */
-
- addto_basenode_table(firstbranch_dev());
- }
- /*--------------------------------------------------------------------------*/
- /* addto_basenode_table: actual work of build_basenode_table.
- * Find and store "base-node" for each node. This is the lowest numbered
- * node that it connects to. We don't do anything with higher numbered nodes.
- * (Unnecessary because of symmetry.) Recursive, for subckts.
- */
- static void addto_basenode_table(stop)
- const branch_t *stop;
- {
- if (isdevice(stop)){
- const branch_t *brh;
- brh = stop;
- do {
- int ii,jj;
- for (ii = 0; brh->n[ii].m != INVALIDNODE; ii++){
- if (brh->n[ii].m != 0)
- for (jj = 0; jj < ii ; jj++)
- lownode(brh->n[ii].m,brh->n[jj].m);
- }
- if (brh->subckt){
- addto_basenode_table(brh->subckt); /* do subckts */
- }
- } while (brh = nextbranch_dev(brh), brh != stop);
- }
- }
- /*--------------------------------------------------------------------------*/
- /* lownode: find the lowest node that each node connects to.
- * (connects to == has distance 1 from)
- */
- static void lownode(node1,node2)
- int node1,node2;
- {
- if (node1 == 0 || node2 == 0) /* node 0 is ground, and doesn't */
- ; /* count as a connection */
- else if ( node1 < basnode[node2] )
- basnode[node2]=node1;
- else if ( node2 < basnode[node1] )
- basnode[node1]=node2;
- }
- /*--------------------------------------------------------------------------*/
- /* alloc_hold_vectors: allocate space to hold data between commands.
- * store voltage between commands, for restart and convergence assistance
- */
- static void alloc_hold_vectors()
- {
- volts = (double*)calloc((unsigned)stats.total_nodes+2, sizeof(double));
- if (!volts)
- error(bERROR, e_om, "volts");
- }
- /*--------------------------------------------------------------------------*/
- /* size_arrays: determine memory needed for main matrix
- * (count non-zero array elememts)
- */
- static unsigned size_arrays()
- {
- int node;
- unsigned space;
-
- space = 0;
- for (node = 0; node <= stats.total_nodes; ++node)
- space += 2 * ( node-basnode[node] ) + 1;
- return space;
- }
- /*--------------------------------------------------------------------------*/
- /* alloc_matrix: allocate main matrix
- * (the thing we do LU decomposition to, to solve)
- */
- static void alloc_matrix(mode,space)
- int mode;
- unsigned space;
- {
- if (space > SEGSIZ/sizeof(double)) /* attempt to trap allocation of */
- error(bERROR, e_om, "seg size"); /* single matrix large enough to */
- /* cause segmentation problems */
- /* also traps space*sizeof(double) */
- /* overflow inside calloc. */
- reals = (double*)calloc(space, sizeof(double));
- if (!reals)
- error(bERROR, e_om, "reals");
- imags = (double*)calloc(space, sizeof(double));
- if (!imags)
- error(bERROR, e_om, "imags");
- }
- /*--------------------------------------------------------------------------*/
- /* alloc_constants: allocate constant vectors
- * (constant is not the right word...) allocate space for the right-side
- * vector (initially current sources, on solution becomes voltages) and copies
- * used for one-time-ago and convergence checking
- */
- static void alloc_constants(mode)
- int mode;
- {
- recon = (double*)calloc((unsigned)stats.total_nodes+2, sizeof(double));
- if (!recon) /* constants terms */
- error(bERROR, e_om, "recon");
- imcon = (double*)calloc((unsigned)stats.total_nodes+2, sizeof(double));
- if (!imcon) /* imaginary (AC) */
- error(bERROR, e_om, "imcon"); /* or next (DC, tr) */
- fwcon = (double*)calloc((unsigned)stats.total_nodes+2, sizeof(double));
- if (!fwcon) /* fwd sub, (dctr) */
- error(bERROR, e_om, "fwcon");
- oldcon = (double*)calloc((unsigned)stats.total_nodes+2, sizeof(double));
- if (!oldcon) /* last time (tr) */
- error(bERROR, e_om, "oldcon");
- nstat = (struct nodestat*)calloc((unsigned)stats.total_nodes+2,
- sizeof(struct nodestat));
- if (!nstat)
- error(bERROR, e_om, "nstat");
- }
- /*--------------------------------------------------------------------------*/
- /* alloc_pointer_table: allocate tables for sparse matrix indexing
- */
- static void alloc_pointer_table(mode)
- int mode;
- {
- redia = (double**)calloc((unsigned)stats.total_nodes+1, sizeof(double*));
- if (!redia) /* pointers to diagonal */
- error(bERROR, e_om, "redia");
- rerow = (double**)calloc((unsigned)stats.total_nodes+1, sizeof(double*));
- if (!rerow) /* row pointers: points to col 0 of each row */
- error(bERROR, e_om, "rerow");
- recol = (double**)calloc((unsigned)stats.total_nodes+1, sizeof(double*));
- if (!recol) /* column pointers: points to row 0 */
- error(bERROR, e_om, "recol");
-
- imdia = (double**)calloc((unsigned)stats.total_nodes+1, sizeof(double*));
- if (!imdia)
- error(bERROR, e_om, "imdia");
- imrow = (double**)calloc((unsigned)stats.total_nodes+1, sizeof(double*));
- if (!imrow)
- error(bERROR, e_om, "imrow");
- imcol = (double**)calloc((unsigned)stats.total_nodes+1, sizeof(double*));
- if (!imcol)
- error(bERROR, e_om, "imcol");
- }
- /*--------------------------------------------------------------------------*/
- /* fill_pointer_table: build tables for sparse matrix access
- * there are 3 tables: row, column and diagonal
- * row pointer points to each row, where column 0 would be if it existed,
- * even though col 0 doesn't actually exist.
- * Matrix is stored by row below the diagonal, and by column, backwards, above,
- * in such a way that the diagonal is in both the row and column.
- */
- static void fill_pointer_table(mode)
- int mode;
- {
- double *repnt, *impnt; /* running location of place in array */
- int node;
-
- repnt = reals; /* fill in pointer tables */
- impnt = imags;
- for (node = 0; node <= stats.total_nodes; ++node){
- recol[node] = repnt - basnode[node]; /* pointers to the bogus */
- rerow[node] = recol[node] + 2*node; /* row or column 0 */
- redia[node] = recol[node] + node;
- repnt = &repnt[2*(node-basnode[node])+1]; /* Next free slot. */
-
- imcol[node] = impnt - basnode[node];
- imrow[node] = imcol[node] + 2*node;
- imdia[node] = imcol[node] + node;
- impnt = &impnt[2*(node-basnode[node])+1];
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/argparse.c'
- then
- echo shar: will not over-write existing file "'src/argparse.c'"
- else
- cat << \SHAR_EOF > 'src/argparse.c'
- /* argparse 04/02/92
- * Copyright 1983-1992 Albert Davis
- * parse name followed by numeric argument from command line
- * to call... list the arguments:
- * each is:
- * string to match (upper case part must match, lower may match
- * user string is not case sensitive
- * variable type (see argparse.h)
- * pointer to variable to fill
- * if enumerated type: value
- * if "2double": second argument
- * end with either null pointer or null string
- *
- * cnt is incrmented to the next argument in the input string
- * returns YES if it did something, NO if not.
- *
- * will try to handle as many arguments as possible.
- */
- #include "ecah.h"
- #include "argparse.h"
- #include "error.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- int argparse();
- /*--------------------------------------------------------------------------*/
- extern const char e_int[];
- /*--------------------------------------------------------------------------*/
- /*VARARGS3*/
- int argparse(cmd,cnt,mode,va_alist)
- const char *cmd;
- int *cnt;
- int mode;
- va_dcl /* ; */
- {
- char *key;
- va_list marker;
- int type;
- int did = NO;
-
- setmatch(cmd,cnt);
- do {
- va_start(marker);
- while (key = va_arg(marker,char*), key && *key){
- type = va_arg(marker,int);
- if (type == aDOUBLE || type == aUDOUBLE || type == aODOUBLE
- || type == a2DOUBLE || type == aSDOUBLE){
- double *arg1;
- double *arg2;
- double offset;
- double scale;
- arg1 = va_arg(marker,double*);
- arg2 = (type==a2DOUBLE) ? va_arg(marker,double*) : (double*)NULL;
- offset = (type==aODOUBLE || type==aOIDOUBLE)
- ? va_arg(marker,double) : 0.;
- scale = (type==aSDOUBLE || type==aSIDOUBLE)
- ? va_arg(marker,double) : 1.;
- if (rematch(key)){
- *arg1 = (type==aUDOUBLE) ? fabs(ctof(cmd,cnt)) : ctof(cmd,cnt);
- *arg1 += offset;
- *arg1 *= scale;
- if (type==aIDOUBLE || type==aOIDOUBLE || type==aSIDOUBLE)
- if (*arg1 != 0.)
- *arg1 = 1. / *arg1;
- if (arg2)
- *arg2 = ctof(cmd,cnt);
- did = YES;
- break;
- }
- }else if (type == aINT || type == aUINT || type == aFINT){
- int *arg;
- arg = va_arg(marker,int*);
- if (rematch(key)){
- switch (type){
- case aUINT: *arg = abs(ctoi(cmd,cnt)); break;
- case aINT: *arg = ctoi(cmd,cnt); break;
- case aFINT: *arg = (int)ctof(cmd,cnt); break;
- }
- did = YES;
- break;
- }
- }else if (type == aENUM || type == aORENUM || type == aANDENUM){
- int *arg;
- int value;
- arg = va_arg(marker,int*);
- value = va_arg(marker,int);
- if (rematch(key)){
- switch (type){
- case aENUM: *arg = value; break;
- case aORENUM: *arg |= value; break;
- case aANDENUM: *arg &= value; break;
- }
- did = YES;
- break;
- }
- }else if (type == aFUNCTION || type == a2FUNCTION){
- void (*arg1)(const char*,int*);
- void (*arg2)(const char*,int*);
- arg1 = va_arg(marker,void*);
- arg2 = (type==a2FUNCTION) ? va_arg(marker,void*) : NULL;
- if (rematch(key)){
- (*arg1)(cmd,cnt);
- if (arg2)
- (*arg2)(cmd,cnt);
- did = YES;
- break;
- }
- }else{
- error(bERROR, e_int, "argparse");
- }
- }
- va_end(marker);
- } while (key && *key && mode==REPEAT);
- return did;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'src/array.c'
- then
- echo shar: will not over-write existing file "'src/array.c'"
- else
- cat << \SHAR_EOF > 'src/array.c'
- /* array 04/02/92
- * Copyright 1983-1992 Albert Davis
- * Access main arrays.
- * Returns pointer to the requested array element.
- * If the place is not allocated, returns pointer to a zero.
- * There are several of these, to access different arrays.
- * Robust versions, with bounds checking, of sorts.
- * For fast versions (macros) see array.h.
- */
- #include "ecah.h"
- #include "error.h"
- #include "status.h"
- #include "declare.h"
- /*--------------------------------------------------------------------------*/
- double *re(int,int);
- double *im(int,int);
- /*--------------------------------------------------------------------------*/
- extern const struct status stats;
- extern const int *basnode; /* lowest node connected to this */
- extern double **rerow, **imrow; /* array of row pointers */
- extern double **recol, **imcol; /* array of column pointers */
- extern double **redia, **imdia; /* array of diagonal pointers */
- extern double *recon, *imcon; /* constant terms */
- extern double zero; /* really a constant, i hope */
- static double trash; /* place to deposit node 0 */
- extern const char e_int[];
- /*--------------------------------------------------------------------------*/
- double *re(row,col)
- int row,col;
- {
- if (col==row)
- return (redia[row]);
- if (col>row){ /* above the diagonal */
- if (row==0)
- return &trash;
- if (col>stats.total_nodes)
- return &recon[row];
- if (row<basnode[col])
- return &zero;
- return (recol[col]+row);
- }
- /* if (col<row) */{ /* below the diagonal */
- if (col==0)
- return &trash;
- if (row>stats.total_nodes)
- error(bERROR, e_int, "array");
- if (col<basnode[row])
- return &zero;
- return (rerow[row]-col);
- }
- }
- /*--------------------------------------------------------------------------*/
- double *im(row,col)
- int row,col;
- {
- if (col==row)
- return (imdia[row]);
- if (col>row){ /* above the diagonal */
- if (row==0)
- return &trash;
- if (col>stats.total_nodes)
- return &imcon[row];
- if (row<basnode[col])
- return &zero;
- return (imcol[col]+row);
- }
- /* if (col<row) */{ /* below the diagonal */
- if (col==0)
- return &trash;
- if (row>stats.total_nodes)
- error(bERROR, e_int, "array");
- if (col<basnode[row])
- return &zero;
- return (imrow[row]-col);
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-