diff --git a/configure.in b/configure.in index 2da35f60b..19c83644e 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ dnl Create a configuration header AM_CONFIG_HEADER(config.h) dnl Initialize automake stuff -AM_INIT_AUTOMAKE(ng-spice-rework,14) +AM_INIT_AUTOMAKE(ng-spice-rework,15pre1) dnl --enable-ftedebug : enable frontend debug macros AC_ARG_ENABLE(ftedebug, @@ -65,7 +65,6 @@ AM_MAINTAINER_MODE dnl Work on compiler options according to system: dnl Set default CFLAG - only use -Wall if we have gcc - AC_PROG_CC if test "x$GCC" = "xyes"; then @@ -420,8 +419,7 @@ src/maths/sparse/Makefile \ src/misc/Makefile \ src/xspice/Makefile \ src/xspice/cm/Makefile \ -src/xspice/icm/Makefile \ -src/xspice/icm/icm_spice2poly/Makefile \ +src/xspice/icm/makedefs \ src/xspice/mif/Makefile \ src/xspice/evt/Makefile \ src/xspice/enh/Makefile \ diff --git a/src/Makefile.am b/src/Makefile.am index a274d08f6..84c113ea7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,49 +15,50 @@ initdatadir = $(pkgdatadir)/scripts initdata_DATA = spinit setplot spectrum -DYNAMIC_DEVICELIBS = \ - spicelib/devices/asrc/libasrc.la \ - spicelib/devices/bjt/libbjt.la \ - spicelib/devices/bsim1/libbsim1.la \ - spicelib/devices/bsim2/libbsim2.la \ - spicelib/devices/bsim3/libbsim3.la \ - spicelib/devices/bsim3v1/libbsim3v1.la \ - spicelib/devices/bsim3v2/libbsim3v2.la \ - spicelib/devices/bsim4/libbsim4.la \ - spicelib/devices/cap/libcap.la \ - spicelib/devices/bsim3soi_pd/libbsim3soipd.la \ - spicelib/devices/bsim3soi_fd/libbsim3soifd.la \ - spicelib/devices/bsim3soi_dd/libbsim3soidd.la \ - spicelib/devices/cccs/libcccs.la \ - spicelib/devices/ccvs/libccvs.la \ - spicelib/devices/ccvs/libccvs.la \ - spicelib/devices/cpl/libcpl.a \ - spicelib/devices/csw/libcsw.la \ - spicelib/devices/dio/libdio.la \ - @EKVLIB@ \ - spicelib/devices/ind/libind.la \ - spicelib/devices/isrc/libisrc.la \ - spicelib/devices/hfet1/libhfet.la \ - spicelib/devices/hfet2/libhfet2.la \ - spicelib/devices/jfet/libjfet.la \ - spicelib/devices/jfet2/libjfet2.la \ - spicelib/devices/ltra/libltra.la \ - spicelib/devices/mes/libmes.la \ - spicelib/devices/mesa/libmesa.la \ - spicelib/devices/mos1/libmos1.la \ - spicelib/devices/mos2/libmos2.la \ - spicelib/devices/mos3/libmos3.la \ - spicelib/devices/mos6/libmos6.la \ - spicelib/devices/mos9/libmos9.la \ - spicelib/devices/res/libres.la \ - spicelib/devices/soi3/libsoi3.la \ - spicelib/devices/sw/libsw.la \ - spicelib/devices/txl/libtxl.a \ - spicelib/devices/tra/libtra.la \ - spicelib/devices/urc/liburc.la \ - spicelib/devices/vccs/libvccs.la \ - spicelib/devices/vcvs/libvcvs.la \ - spicelib/devices/vsrc/libvsrc.la +DYNAMIC_DEVICELIBS = \ + spicelib/devices/asrc/libasrc.a \ + spicelib/devices/bjt/libbjt.a \ + spicelib/devices/bsim1/libbsim1.a \ + spicelib/devices/bsim2/libbsim2.a \ + spicelib/devices/bsim3/libbsim3.a \ + spicelib/devices/bsim3v1/libbsim3v1.a \ + spicelib/devices/bsim3v2/libbsim3v2.a \ + spicelib/devices/bsim4/libbsim4.a \ + spicelib/devices/cap/libcap.a \ + spicelib/devices/bsim3soi_pd/libbsim3soipd.a \ + spicelib/devices/bsim3soi_fd/libbsim3soifd.a \ + spicelib/devices/bsim3soi_dd/libbsim3soidd.a \ + spicelib/devices/cccs/libcccs.a \ + spicelib/devices/ccvs/libccvs.a \ + spicelib/devices/ccvs/libccvs.a \ + spicelib/devices/cpl/libcpl.a \ + spicelib/devices/csw/libcsw.a \ + spicelib/devices/dio/libdio.a \ + @EKVLIB@ \ + spicelib/devices/ind/libind.a \ + spicelib/devices/isrc/libisrc.a \ + spicelib/devices/hfet1/libhfet.a \ + spicelib/devices/hfet2/libhfet2.a \ + spicelib/devices/jfet/libjfet.a \ + spicelib/devices/jfet2/libjfet2.a \ + spicelib/devices/ltra/libltra.a \ + spicelib/devices/mes/libmes.a \ + spicelib/devices/mesa/libmesa.a \ + spicelib/devices/mos1/libmos1.a \ + spicelib/devices/mos2/libmos2.a \ + spicelib/devices/mos3/libmos3.a \ + spicelib/devices/mos6/libmos6.a \ + spicelib/devices/mos9/libmos9.a \ + spicelib/devices/res/libres.a \ + spicelib/devices/soi3/libsoi3.a \ + spicelib/devices/sw/libsw.a \ + spicelib/devices/txl/libtxl.a \ + spicelib/devices/tra/libtra.a \ + spicelib/devices/urc/liburc.a \ + spicelib/devices/vccs/libvccs.a \ + spicelib/devices/vcvs/libvcvs.a \ + spicelib/devices/vsrc/libvsrc.a + ## ----- Note that I moved this stuff to here because it was causing automake @@ -67,7 +68,6 @@ DYNAMIC_DEVICELIBS = \ ## poly added to dynamic libs by SDB on 6.1.2003 ## xspice/icm/poly/libpoly.a - ## Build ngspice first: ngspice_SOURCES = \ @@ -123,8 +123,6 @@ ngnutmeg_LDADD = \ maths/poly/libpoly.a \ misc/libmisc.a - - ## help: nghelp_SOURCES = nghelp.c @@ -135,7 +133,6 @@ nghelp_LDADD = \ frontend/libfte.a \ misc/libmisc.a - ## sconvert: ngsconvert_SOURCES = ngsconvert.c @@ -147,7 +144,6 @@ ngsconvert_LDADD = \ frontend/parser/libparser.a \ misc/libmisc.a - ## proc2mod: ngproc2mod_SOURCES = ngproc2mod.c diff --git a/src/conf.c b/src/conf.c index ca6f1d6a6..3be431736 100644 --- a/src/conf.c +++ b/src/conf.c @@ -5,7 +5,7 @@ #include "conf.h" char Spice_Version[ ] = VERSION; -char Spice_Notice[ ] = "Please submit bug-reports to: ng-spice-bugs@ieee.ing.uniroma1.it"; +char Spice_Notice[ ] = "Please submit bug-reports to: ngspice-devel@lists.sourceforge.net"; char Spice_Build_Date[ ] = NGSPICEBUILDDATE; /* char *Spice_Exec_Dir = "/spice_win/bin"; @@ -23,7 +23,7 @@ int AsciiRawFile = 0; #endif -char *Bug_Addr = "ng-spice-bugs@ieee.ing.uniroma1.it"; +char *Bug_Addr = "ngspice-devel@lists.sourceforge.net"; char *Spice_Host = ""; char *Spiced_Log = ""; diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c index b0d338b93..bec8db9b9 100644 --- a/src/frontend/misccoms.c +++ b/src/frontend/misccoms.c @@ -117,7 +117,7 @@ com_bug(wordlist *wl) void com_bug(wordlist *wl) { - fprintf(cp_out, "Send mail to the address ng-spice@ieee.ing.uniroma1.it\n"); + fprintf(cp_out, "Send mail to the address ngspice-devel@lists.sourceforge.net\n"); return; } diff --git a/src/spinit b/src/spinit index 6695ff437..3ca6af8c2 100644 --- a/src/spinit +++ b/src/spinit @@ -4,4 +4,10 @@ alias acct rusage all set x11lineararcs * For SPICE2 POLYs, edit the below line to point to the location * of your codemode. -* codemodel /usr/local/src/ngspice/src/xspice/icm/spice2poly.cm +* codemodel /usr/lib/spice/spice2poly.cm + +* The other codemodels +* codemodel /usr/lib/spice/analog.cm +* codemodel /usr/lib/spice/digital.cm +* codemodel /usr/lib/spice/xtradev.cm +* codemodel /usr/lib/spice/xtraevt.cm diff --git a/src/xspice/icm/Makefile b/src/xspice/icm/Makefile new file mode 100644 index 000000000..2bb1c586c --- /dev/null +++ b/src/xspice/icm/Makefile @@ -0,0 +1,120 @@ +# The master makefile to make spiceopuse (TM) like codemodels +# Under the GPLV2 or later license +# 2003 - Stefan Jones + +include $(TOPDIR)makedefs + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include .deps/ifspec.P +-include .deps/cfunc.P +-include .deps/udnfunc.P +-include .deps/cm.P +-include .deps/dlmain.P + +UPMAKE = make -f $(TOPDIR)../Makefile TOPDIR=$(TOPDIR)../ + +MAKE = make -f $(TOPDIR)Makefile TOPDIR=$(TOPDIR) + +COMPILE = $(CC) $(INCLUDES) $(CFLAGS) + +INSTALL_DATA = ${INSTALL} -m 644 + +all: + @amf=$$2; for x in $(CMDIRS) ; do \ + ( cd $$x && $(UPMAKE) $$x-mods ) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + +install: all + $(mkinstalldirs) $(DESTDIR)$(libdir)/spice + @for x in $(CMDIRS) ; do \ + echo "$(INSTALL_DATA) $$x/$$x.cm $(DESTDIR)$(libdir)/spice"; \ + $(INSTALL_DATA) $$x/$$x.cm $(DESTDIR)$(libdir)/spice \ + || exit 1; \ + done + +clean: + @amf=$$2; for x in $(CMDIRS) ; do \ + ( cd $$x && $(UPMAKE) $$x-mods-clean ) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + -rm -rf .deps + +ifspec.c: ifspec.ifs + -rm -f $@ + $(CMPP) -ifs + +cfunc.c: cfunc.mod + -rm -f $@ + $(CMPP) -mod + +dlmain.c: $(TOPDIR)/dlmain.c + -cp $(TOPDIR)/dlmain.c . + +objects.inc cmextrn.h cminfo.h udnextrn.h udninfo.h: modpath.lst udnpath.lst + -rm -f cmextrn.h cminfo.h objects.inc udnextrn.h udninfo.h + $(CMPP) -lst + +dlmain.o: cmextrn.h cminfo.h udnextrn.h udninfo.h + +%.cm: dlmain.o objects.inc + @echo $@: objects.inc dlmain.o \\ > .deps/cm.P + @for x in `cat modpath.lst` ; do \ + echo $$x/cfunc.o $$x/ifspec.o \\ >> .deps/cm.P ; done + @for x in `cat udnpath.lst` ; do \ + echo $$x/udnfunc.o \\ >> .deps/cm.P ; done + @echo "" >> .deps/cm.P + $(COMPILE) $(LDFLAGS) -o $@ `awk '{ print $$1 }' objects.inc` dlmain.o + +%-mods: modpath.lst udnpath.lst + @amf=$$2; for x in `cat modpath.lst` ; do \ + ( cd $$x && $(UPMAKE) objs ) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + @amf=$$2; for x in `cat udnpath.lst` ; do \ + ( cd $$x && $(UPMAKE) uobjs ) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + @target=`echo $@ | sed s/-mods//`; $(MAKE) $$target.cm + +%-mods-clean: + @target=`echo $@ | sed s/-mods-clean//` && rm -f $$target.cm + @amf=$$2; for x in `cat modpath.lst` ; do \ + ( cd $$x && $(UPMAKE) objs-clean ) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + @amf=$$2; for x in `cat udnpath.lst` ; do \ + ( cd $$x && $(UPMAKE) uobjs-clean ) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + -rm -f cmextrn.h cminfo.h objects.inc udnextrn.h udninfo.h \ + dlmain.c dlmain.o + -rm -rf .deps + + +objs: ifspec.o cfunc.o + +objs-clean: + -rm -f cfunc.c ifspec.c cfunc.o ifspec.o + -rm -rf .deps + +uobjs: udnfunc.o + +uobjs-clean: + -rm -f udnfunc.o + -rm -rf .deps + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +makedefs: $(srcdir)/makedefs.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + diff --git a/src/xspice/icm/analog/climit/cfunc.mod b/src/xspice/icm/analog/climit/cfunc.mod new file mode 100644 index 000000000..79776b79f --- /dev/null +++ b/src/xspice/icm/analog/climit/cfunc.mod @@ -0,0 +1,266 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE climit/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 June 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 26 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the adc_bridge + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + void cm_smooth_discontinuity(); + + CMmacros.h cm_message_send(); + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + + +/*============================================================================== + +FUNCTION cm_climit() + +AUTHORS + + 6 June 1991 Jeffrey P. Murray + +MODIFICATIONS + + 26 Sept 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the climit code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + void cm_smooth_discontinuity(); + + CMmacros.h cm_message_send(); + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_CLIMIT ROUTINE ===*/ + +void cm_climit(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + /* Define error message string constants */ + + char *climit_range_error = "\n**** ERROR ****\n* CLIMIT function linear range less than zero. *\n"; + + + double lower_delta, /* lower delta value parameter */ + upper_delta, /* upper delta value parameter */ + limit_range, /* range of output below + (out_upper_limit - upper_delta) + or above (out_lower_limit + lower_delta) + within which smoothing will be applied */ + gain, /* gain parameter */ + threshold_upper, /* = out_upper_limit - upper_delta */ + threshold_lower, /* = out_lower_limit + lower_delta */ + linear_range, /* = threshold_upper - threshold_lower */ + out_lower_limit, /* output lower limit parameter */ + out_upper_limit, /* output upper limit parameter */ + out, /* originally-calculated output value */ + limited_out, /* output value after limiting */ + pout_pin, /* partial derivative of output w.r.t.input */ + pout_pcntl_upper, /* partial derivative of output w.r.t. + cntl_upper input */ + pout_pcntl_lower, /* partial derivative of output w.r.t. + cntl_lower input */ + junk; /* dummy variable */ + + Mif_Complex_t ac_gain; /* AC gain */ + + + + /* Retrieve frequently used parameters... */ + + lower_delta = PARAM(lower_delta); + upper_delta = PARAM(upper_delta); + limit_range = PARAM(limit_range); + gain = PARAM(gain); + + + /* Find Upper & Lower Limits */ + + out_lower_limit = INPUT(cntl_lower) + lower_delta; + out_upper_limit = INPUT(cntl_upper) - upper_delta; + + + if (PARAM(fraction) == MIF_TRUE) /* Set range to absolute value */ + limit_range = limit_range * + (out_upper_limit - out_lower_limit); + + + + threshold_upper = out_upper_limit - /* Set Upper Threshold */ + limit_range; + threshold_lower = out_lower_limit + /* Set Lower Threshold */ + limit_range; + linear_range = threshold_upper - threshold_lower; + + + /* Test the linear region & make sure there IS one... */ + if (linear_range < 0.0) { + /* This INIT test keeps the models from outputting + an error message the first time through when all + the inputs are initialized to zero */ + if( (INIT != 1) && (0.0 != TIME) ){ + cm_message_send(climit_range_error); + } + limited_out = 0.0; + pout_pin = 0.0; + pout_pcntl_lower = 0.0; + pout_pcntl_upper = 0.0; + return; + } + + /* Compute Un-Limited Output */ + out = gain * (PARAM(in_offset) + INPUT(in)); + + + if (out < threshold_lower) { /* Limit Out @ Lower Bound */ + + pout_pcntl_upper= 0.0; + + if (out > (out_lower_limit - limit_range)) { /* Parabolic */ + cm_smooth_corner(out,out_lower_limit,out_lower_limit, + limit_range,0.0,1.0,&limited_out, + &pout_pin); + pout_pin = gain * pout_pin; + cm_smooth_discontinuity(out,out_lower_limit,1.0,threshold_lower, + 0.0,&pout_pcntl_lower,&junk); + } + else { /* Hard-Limited Region */ + limited_out = out_lower_limit; + pout_pin = 0.0; + pout_pcntl_lower = 1.0; + } + } + else { + if (out > threshold_upper) { /* Limit Out @ Upper Bound */ + + pout_pcntl_lower= 0.0; + + if (out < (out_upper_limit+limit_range)) { /* Parabolic */ + cm_smooth_corner(out,out_upper_limit,out_upper_limit, + limit_range,1.0,0.0,&limited_out, + &pout_pin); + pout_pin = gain * pout_pin; + cm_smooth_discontinuity(out,threshold_upper,0.0,out_upper_limit, + 1.0,&pout_pcntl_upper,&junk); + } + else { /* Hard-Limited Region */ + limited_out = out_upper_limit; + pout_pin = 0.0; + pout_pcntl_upper = 1.0; + } + } + else { /* No Limiting Needed */ + limited_out = out; + pout_pin = gain; + pout_pcntl_lower = 0.0; + pout_pcntl_upper = 0.0; + } + } + + if (ANALYSIS != MIF_AC) { /* DC & Transient Analyses */ + + OUTPUT(out) = limited_out; + PARTIAL(out,in) = pout_pin; + PARTIAL(out,cntl_lower) = pout_pcntl_lower; + PARTIAL(out,cntl_upper) = pout_pcntl_upper; + + } + else { /* AC Analysis */ + ac_gain.real = pout_pin; + ac_gain.imag= 0.0; + AC_GAIN(out,in) = ac_gain; + + ac_gain.real = pout_pcntl_lower; + ac_gain.imag= 0.0; + AC_GAIN(out,cntl_lower) = ac_gain; + + ac_gain.real = pout_pcntl_upper; + ac_gain.imag= 0.0; + AC_GAIN(out,cntl_upper) = ac_gain; + + } +} diff --git a/src/xspice/icm/analog/climit/ifspec.ifs b/src/xspice/icm/analog/climit/ifspec.ifs new file mode 100644 index 000000000..5bb7288ae --- /dev/null +++ b/src/xspice/icm/analog/climit/ifspec.ifs @@ -0,0 +1,77 @@ + + /* INTERFACE TABLE FOR CODE MODEL CLIMIT */ + + +NAME_TABLE: + + +C_Function_Name: cm_climit +Spice_Model_Name: climit +Description: "controlled limiter block" + + +PORT_TABLE: + + +Port_Name: in cntl_upper +Description: "input" "upper lim. control input" +Direction: in in +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id,vnam] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + +PORT_TABLE: + +Port_Name: cntl_lower out +Description: "lower limit control input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + + + +PARAMETER_TABLE: + + +Parameter_Name: in_offset gain +Description: "input offset" "gain" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + + +Parameter_Name: upper_delta lower_delta +Description: "output upper delta" "output lower delta" +Data_Type: real real +Default_Value: 0.0 0.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + + +Parameter_Name: limit_range fraction +Description: "upper & lower sm. range" "smoothing %/abs switch" +Data_Type: real boolean +Default_Value: 1.0e-6 FALSE +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + diff --git a/src/xspice/icm/analog/d_dt/cfunc.mod b/src/xspice/icm/analog/d_dt/cfunc.mod new file mode 100644 index 000000000..cad9159a9 --- /dev/null +++ b/src/xspice/icm/analog/d_dt/cfunc.mod @@ -0,0 +1,249 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_dt/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 June 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the d_dt + (differentiator) code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_integrate() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_d_dt() + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_dt code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_integrate() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_DT ROUTINE ===*/ + + +void cm_d_dt(ARGS) + +{ + + double *in, /* current input value */ + *in_old, /* previous input value */ + out, /* output */ + dum, /* fake input value...used for truncation + error checking */ + gain, /* gain parameter */ + out_offset, /* output offset parameter */ + out_lower_limit, /* output mower limit */ + out_upper_limit, /* output upper limit */ + limit_range, /* range of output below out_upper_limit + or above out_lower_limit to which + smoothing will be applied */ + pout_pin, /* partial derivative of output + w.r.t. input */ + dumpout_pin, /* fake partial derivative of output + w.r.t. input (for use with integration */ + delta, /* delta time value = TIME - T(1) */ + pout_gain; /* temporary storage for partial + returned by smoothing function + (subsequently multiplied w/pout_pin) */ + + Mif_Complex_t ac_gain; /* AC gain */ + + + + /** Retrieve frequently used parameters (used by all analyses)... **/ + + gain = PARAM(gain); + + + + if (ANALYSIS != MIF_AC) { /**** DC & Transient Analyses ****/ + + /** Retrieve frequently used parameters... **/ + + out_offset = PARAM(out_offset); + out_lower_limit = PARAM(out_lower_limit); + out_upper_limit = PARAM(out_upper_limit); + limit_range = PARAM(limit_range); + + + /** Test for INIT; if so, allocate storage, otherwise, retrieve + previous timepoint input value... **/ + + if (INIT==1) { /* First pass...allocate storage for previous state. */ + /* Also, calculate roughly where the current output */ + /* will be and use this value to define current state. */ + + in = cm_analog_alloc(TRUE,sizeof(double)); + in_old = cm_analog_get_ptr(TRUE,1); + + } + else { /* Allocation not necessary...retrieve previous values */ + + in = cm_analog_get_ptr(TRUE,0); /* Set out pointer to current + time storage */ + in_old = cm_analog_get_ptr(TRUE,1); /* Set old-output-state pointer + to previous time storage */ + } + + + if ( 0.0 == TIME ) { /*** Test to see if this is the first ***/ + /*** timepoint calculation...if ***/ + *in_old = *in = INPUT(in); /*** so, return a zero d/dt value. ***/ + out = 0.0; /*** so, return a zero d/dt value. ***/ + pout_pin = 0.0; + } + else { /*** Calculate value of d_dt.... ***/ + delta = TIME - T(1); + *in = INPUT(in); + out = gain * (*in - *in_old) / delta + out_offset; + pout_pin = gain / delta; + } + + + /*** Smooth output if it is within limit_range of + out_lower_limit or out_upper_limit. ***/ + + if (out < (out_lower_limit - limit_range)) { /* At lower limit. */ + out = out_lower_limit; + pout_pin = 0.0; + } + else { + if (out < (out_lower_limit + limit_range)) { /* Lower smoothing range */ + cm_smooth_corner(out,out_lower_limit,out_lower_limit,limit_range, + 0.0,1.0,&out,&pout_gain); + pout_pin = pout_pin * pout_gain; + } + else { + if (out > (out_upper_limit + limit_range)) { /* At upper limit */ + out = out_upper_limit; + pout_pin = 0.0; + } + else { + if (out > (out_upper_limit - limit_range)) { /* Upper smoothing region */ + cm_smooth_corner(out,out_upper_limit,out_upper_limit,limit_range, + 1.0,0.0,&out,&pout_gain); + pout_pin = pout_pin * pout_gain; + } + } + } + } + + /** Output values for DC & Transient **/ + + OUTPUT(out) = out; + PARTIAL(out,in) = pout_pin; + /* this cm_analog_integrate call is required in order to force + truncation error to be evaluated */ + cm_analog_integrate(out,&dum,&dumpout_pin); + + } + + else { /**** AC Analysis...output (0.0,s*gain) ****/ + ac_gain.real = 0.0; + ac_gain.imag= gain * RAD_FREQ; + AC_GAIN(out,in) = ac_gain; + } +} + + + + + diff --git a/src/xspice/icm/analog/d_dt/ifspec.ifs b/src/xspice/icm/analog/d_dt/ifspec.ifs new file mode 100644 index 000000000..2193e5348 --- /dev/null +++ b/src/xspice/icm/analog/d_dt/ifspec.ifs @@ -0,0 +1,79 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog d_dt (differentiator) code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_d_dt +Spice_Model_Name: d_dt +Description: "differentiator block" + + +PORT_TABLE: + + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + + +Parameter_Name: out_offset gain +Description: "output offset" "gain" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + + +Parameter_Name: out_lower_limit out_upper_limit +Description: "output lower limit" "output upper limit" +Data_Type: real real +Default_Value: - - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + + +Parameter_Name: limit_range +Description: "upper & lower sm. range" +Data_Type: real +Default_Value: 1.0e-6 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + diff --git a/src/xspice/icm/analog/divide/cfunc.mod b/src/xspice/icm/analog/divide/cfunc.mod new file mode 100644 index 000000000..76fbf3289 --- /dev/null +++ b/src/xspice/icm/analog/divide/cfunc.mod @@ -0,0 +1,204 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE divide/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the divide code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_divide() + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + This function implements the divide code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + + +/*=== CM_DIVIDE ROUTINE ===*/ + + +void cm_divide(ARGS) + +{ + double den_lower_limit; /* denominator lower limit */ + double den_domain; /* smoothing range for the lower limit */ + double threshold_upper; /* value above which smoothing occurs */ + double threshold_lower; /* value below which smoothing occurs */ + double numerator; /* numerator input */ + double denominator; /* denominator input */ + double limited_den; /* denominator value if limiting is needed */ + double den_partial; /* partial of the output wrt denominator */ + double out_gain; /* output gain */ + double num_gain; /* numerator gain */ + double den_gain; /* denominator gain */ + + Mif_Complex_t ac_gain; + + + + /* Retrieve frequently used parameters... */ + + den_lower_limit = PARAM(den_lower_limit); + den_domain = PARAM(den_domain); + out_gain = PARAM(out_gain); + num_gain = PARAM(num_gain); + den_gain = PARAM(den_gain); + + + if (PARAM(fraction) == MIF_TRUE) /* Set domain to absolute value */ + den_domain = den_domain * den_lower_limit; + + threshold_upper = den_lower_limit + /* Set Upper Threshold */ + den_domain; + + threshold_lower = den_lower_limit - /* Set Lower Threshold */ + den_domain; + + numerator = (INPUT(num) + PARAM(num_offset)) * num_gain; + denominator = (INPUT(den) + PARAM(den_offset)) * den_gain; + + if ((denominator < threshold_upper) && (denominator >= 0)) { /* Need to limit den...*/ + + if (denominator > threshold_lower) /* Parabolic Region */ + cm_smooth_corner(denominator,den_lower_limit, + den_lower_limit,den_domain,0.0,1.0, + &limited_den,&den_partial); + + else { /* Hard-Limited Region */ + limited_den = den_lower_limit; + den_partial = 0.0; + } + } + else + if ((denominator > -threshold_upper) && (denominator < 0)) { /* Need to limit den...*/ + if (denominator < -threshold_lower) /* Parabolic Region */ + cm_smooth_corner(denominator,-den_lower_limit, + -den_lower_limit,den_domain,0.0,1.0, + &limited_den,&den_partial); + + else { /* Hard-Limited Region */ + limited_den = -den_lower_limit; + den_partial = 0.0; + } + } + else { /* No limiting needed */ + limited_den = denominator; + den_partial = 1.0; + } + + if (ANALYSIS != MIF_AC) { + + OUTPUT(out) = PARAM(out_offset) + out_gain * + ( numerator/limited_den ); + PARTIAL(out,num) = out_gain * num_gain / limited_den; + PARTIAL(out,den) = -out_gain * numerator * den_gain * + den_partial / (limited_den * limited_den); + + } + else { + ac_gain.real = out_gain * num_gain / limited_den; + ac_gain.imag= 0.0; + AC_GAIN(out,num) = ac_gain; + + ac_gain.real = -out_gain * numerator * den_gain * + den_partial / (limited_den * limited_den); + ac_gain.imag= 0.0; + AC_GAIN(out,den) = ac_gain; + } + +} diff --git a/src/xspice/icm/analog/divide/ifspec.ifs b/src/xspice/icm/analog/divide/ifspec.ifs new file mode 100644 index 000000000..f3fd0a4c3 --- /dev/null +++ b/src/xspice/icm/analog/divide/ifspec.ifs @@ -0,0 +1,108 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog divide code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_divide +Spice_Model_Name: divide +Description: "divider block" + + +PORT_TABLE: + + +Port_Name: num den out +Description: "numerator" "denominator" "output" +Direction: in in out +Default_Type: v v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no no +Vector_Bounds: - - - +Null_Allowed: no no no + + + +PARAMETER_TABLE: + + +Parameter_Name: num_offset num_gain +Description: "numerator offset" "numerator gain" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + + +Parameter_Name: den_offset den_gain +Description: "denominator offset" "denominator gain" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + + +Parameter_Name: den_lower_limit den_domain +Description: "denominator lower limit" "denominator smoothing domain" +Data_Type: real real +Default_Value: 1.0e-10 1.0e-16 +Limits: [1.0e-10 -] - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + + +Parameter_Name: fraction +Description: "smoothing fraction/absolute value switch" +Data_Type: boolean +Default_Value: false +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + + +PARAMETER_TABLE: + + +Parameter_Name: out_gain out_offset +Description: "output gain" "output offset" +Data_Type: real real +Default_Value: 1.0 0.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + diff --git a/src/xspice/icm/analog/gain/cfunc.mod b/src/xspice/icm/analog/gain/cfunc.mod new file mode 100644 index 000000000..7f40efb93 --- /dev/null +++ b/src/xspice/icm/analog/gain/cfunc.mod @@ -0,0 +1,130 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE gain/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the gain code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_gain() + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + This function implements the gain code model. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + + +/*=== CM_GAIN ROUTINE ===*/ + + +void cm_gain(ARGS) /* structure holding parms, inputs, outputs, etc. */ +{ + Mif_Complex_t ac_gain; + + if(ANALYSIS != MIF_AC) { + OUTPUT(out) = PARAM(out_offset) + PARAM(gain) * + ( INPUT(in) + PARAM(in_offset)); + PARTIAL(out,in) = PARAM(gain); + } + else { + ac_gain.real = PARAM(gain); + ac_gain.imag= 0.0; + AC_GAIN(out,in) = ac_gain; + } + +} diff --git a/src/xspice/icm/analog/gain/ifspec.ifs b/src/xspice/icm/analog/gain/ifspec.ifs new file mode 100644 index 000000000..063d394ea --- /dev/null +++ b/src/xspice/icm/analog/gain/ifspec.ifs @@ -0,0 +1,54 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog gain code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_gain +Spice_Model_Name: gain +Description: "A simple gain block" + + +PORT_TABLE: + + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + + +PARAMETER_TABLE: + + +Parameter_Name: in_offset gain out_offset +Description: "input offset" "gain" "output offset" +Data_Type: real real real +Default_Value: 0.0 1.0 0.0 +Limits: - - - +Vector: no no no +Vector_Bounds: - - - +Null_Allowed: yes yes yes + + diff --git a/src/xspice/icm/analog/hyst/cfunc.mod b/src/xspice/icm/analog/hyst/cfunc.mod new file mode 100644 index 000000000..02c003858 --- /dev/null +++ b/src/xspice/icm/analog/hyst/cfunc.mod @@ -0,0 +1,360 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE hyst/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the hyst code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include "cm_hyst.h" + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + +/*============================================================================== + +FUNCTION void hyst() + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + This function implements the hyst code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + + +/*=== CM_HYST ROUTINE ===*/ + + +/************************************************************************* +* BEHAVIOR OF HYSTERESIS: * +* out hyst hyst * +* ^ ____/\_____ ____/\_____ * +* | / \/ \ * +* | x_fall_linear x_rise_zero * +* out_upper_limit- - *----<-------------<------*-------> * +* | /| /| /| * +* | / /in_high / * +* | / | / | / | * +* | / / __/ * +* | |/_ | / | /| | * +* | / / / * +* | / | / | / | * +* <------O----/------------/------------/-----------------------> in * +* | | / | / | / * +* | / / / * +* <--------*------->----|---->-------* - - - - out_lower_limit * +* x_fall_zero in_low x_rise_linear * +* V * +* * +* input_domain defines "in" increment below & above the "*" points * +* shown, within which smoothing of the d(out)/d(in) values * +* occurs...this prevents abrupt changes in d(out)/d(in) which * +* could prevent the simulator from reaching convergence during * +* a transient or DC analysis. * +* * +**************************************************************************/ + +/**************************************************************************/ +/* Usage of cm_smooth_corner: */ +/* */ +/* void cm_smooth_corner(double x_input, double x_center, double y_center, */ +/* double domain, double lower_slope, */ +/* double upper_slope,double *y_output, double *dy_dx) */ +/* */ +/**************************************************************************/ + + + +void cm_hyst(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + double in, /* input to hysteresis block */ + out, /* output from hysteresis block */ + in_low, /* lower input value for hyst=0 at which + the transfer curve changes from constant + to linear */ + in_high, /* upper input value for hyst=0 at which + the transfer curve changes from constant + to linear */ + hyst, /* the hysteresis value (see above diagram) */ + out_lower_limit, /* the minimum output value from the block */ + out_upper_limit, /* the maximum output value from the block */ + input_domain, /* the delta value of the input above and + below in_low and in_high within which + smoothing will be applied to the output + in order to maintain continuous first partial + derivatives. */ + slope, /* calculated rise and fall slope for the block */ + pout_pin, /* partial derivative of output w.r.t. input */ + x_rise_linear, /* = in_low + hyst */ + x_rise_zero, /* = in_high + hyst */ + x_fall_linear, /* = in_high - hyst */ + x_fall_zero; /* = in_low - hyst */ + + Boolean_t *hyst_state, /* TRUE => input is on lower leg of + hysteresis curve, between -infinity + and in_high + hyst. + FALSE => input is on upper leg + of hysteresis curve, between + in_low - hyst and +infinity */ + *old_hyst_state; /* previous value of *hyst_state */ + + Mif_Complex_t ac_gain; /* AC gain */ + + + + + + /** Retrieve frequently used parameters... **/ + + in_low = PARAM(in_low); + in_high = PARAM(in_high); + hyst = PARAM(hyst); + out_lower_limit = PARAM(out_lower_limit); + out_upper_limit = PARAM(out_upper_limit); + input_domain = PARAM(input_domain); + + + + + /** Calculate Hysteresis Linear Region Slopes & Derived Values **/ + + + /* Define slope of rise and fall lines when not being smoothed */ + + slope = (out_upper_limit - out_lower_limit)/(in_high - in_low); + + x_rise_linear = in_low + hyst; /* Breakpoint - x rising to + linear region */ + x_rise_zero = in_high + hyst; /* Breakpoint - x rising to + zero-slope (out_upper_limit) */ + x_fall_linear = in_high - hyst; /* Breakpoint - x falling to + linear region */ + x_fall_zero = in_low - hyst; /* Breakpoint - x falling to + zero-slope (out_lower_limit) */ + + if (PARAM(fraction) == MIF_TRUE) /* Set range to absolute value */ + input_domain = input_domain * (in_high - in_low); + + + + + /** Retrieve frequently used inputs... **/ + + in = INPUT(in); + + + + /** Test for INIT; if so, allocate storage, otherwise, retrieve + previous timepoint value for output... **/ + + if (INIT==1) { /* First pass...allocate storage for previous state. */ + /* Also, calculate roughly where the current output */ + /* will be and use this value to define current state. */ + + hyst_state = cm_analog_alloc(TRUE,sizeof(Boolean_t)); + old_hyst_state = cm_analog_get_ptr(TRUE,1); + + if (in < x_rise_zero + input_domain) { /* Set state to X_RISING */ + *old_hyst_state = X_RISING; + } + else { + *old_hyst_state = X_FALLING; + } + } + else { /* Allocation not necessary...retrieve previous values */ + + hyst_state = cm_analog_get_ptr(TRUE,0); /* Set out pointer to current + time storage */ + old_hyst_state = cm_analog_get_ptr(TRUE,1); /* Set old-output-state pointer + to previous time storage */ + } + + + + /** Set *hyst_out = *old_hyst_out, unless changed below... + we don't need the last iteration value of *hyst_state. **/ + + *hyst_state = *old_hyst_state; + + + + + /*** Calculate value of hyst_state, pout_pin.... ***/ + + if (*old_hyst_state == X_RISING) { /* Assume calculations on lower */ + /* hysteresis section (x rising) */ + + if ( in <= x_rise_linear - input_domain ) { /* Output @ lower limit */ + + out = out_lower_limit; + pout_pin = 0.0; + } + else { + if ( in <= x_rise_linear + input_domain ) { /* lower smoothing region */ + cm_smooth_corner(in,x_rise_linear,out_lower_limit,input_domain, + 0.0,slope,&out,&pout_pin); + } + else { + if (in <= x_rise_zero - input_domain) { /* Rising linear region */ + out = (in - x_rise_linear)*slope + out_lower_limit; + pout_pin = slope; + } + else { + if (in <= x_rise_zero + input_domain) { /* Upper smoothing region */ + cm_smooth_corner(in,x_rise_zero,out_upper_limit,input_domain, + slope,0.0,&out,&pout_pin); + } + else { /* input has transitioned to X_FALLING region... */ + out = out_upper_limit; + pout_pin = 0.0; + *hyst_state = X_FALLING; + } + } + } + } + } + else { /* Assume calculations on upper hysteresis section (x falling) */ + + if ( in >= x_fall_linear + input_domain ) { /* Output @ upper limit */ + + out = out_upper_limit; + pout_pin = 0.0; + } + else { + if ( in >= x_fall_linear - input_domain ) { /* Upper smoothing region */ + cm_smooth_corner(in,x_fall_linear,out_upper_limit,input_domain, + slope,0.0,&out,&pout_pin); + } + else { + if (in >= x_fall_zero + input_domain) { /* Falling linear region */ + out = (in - x_fall_zero)*slope + out_lower_limit; + pout_pin = slope; + } + else { + if (in >= x_fall_zero - input_domain) { /* Lower smoothing region */ + cm_smooth_corner(in,x_fall_zero,out_lower_limit,input_domain, + 0.0,slope,&out,&pout_pin); + } + else { /* input has transitioned to X_RISING region... */ + out = out_lower_limit; + pout_pin = 0.0; + *hyst_state = X_RISING; + } + } + } + } + } + + + + if (ANALYSIS != MIF_AC) { /* DC & Transient Analyses */ + + OUTPUT(out) = out; + PARTIAL(out,in) = pout_pin; + + } + else { /* AC Analysis */ + ac_gain.real = pout_pin; + ac_gain.imag= 0.0; + AC_GAIN(out,in) = ac_gain; + + } +} + + + + + diff --git a/src/xspice/icm/analog/hyst/cm_hyst.h b/src/xspice/icm/analog/hyst/cm_hyst.h new file mode 100644 index 000000000..e65d358f6 --- /dev/null +++ b/src/xspice/icm/analog/hyst/cm_hyst.h @@ -0,0 +1,75 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE hyst/cm_hyst.h + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 23 Oct 1990 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains additional header information for + the hyst code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +REFERENCED FILES + + N/A + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + +#define HYST 1 +#define X_RISING TRUE +#define X_FALLING FALSE + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + diff --git a/src/xspice/icm/analog/hyst/ifspec.ifs b/src/xspice/icm/analog/hyst/ifspec.ifs new file mode 100644 index 000000000..c57cf1f36 --- /dev/null +++ b/src/xspice/icm/analog/hyst/ifspec.ifs @@ -0,0 +1,87 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog hyst code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_hyst +Spice_Model_Name: hyst +Description: "hysteresis block" + + +PORT_TABLE: + + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + +PARAMETER_TABLE: + +Parameter_Name: in_low in_high +Description: "input low value" "input high value" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: hyst out_lower_limit +Description: "hysteresis" "output lower limit" +Data_Type: real real +Default_Value: 0.1 0.0 +Limits: [0 -] - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: out_upper_limit input_domain +Description: "output upper limit" "input smoothing domain" +Data_Type: real real +Default_Value: 1.0 0.01 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: fraction +Description: "smoothing percent/abs switch" +Data_Type: boolean +Default_Value: TRUE +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + diff --git a/src/xspice/icm/analog/ilimit/cfunc.mod b/src/xspice/icm/analog/ilimit/cfunc.mod new file mode 100644 index 000000000..5d7e54313 --- /dev/null +++ b/src/xspice/icm/analog/ilimit/cfunc.mod @@ -0,0 +1,442 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE ilimit/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the ilimit code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + void cm_smooth_discontinuity(); + void cm_climit_fcn() + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_ilimit() + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the ilimit code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + void cm_smooth_discontinuity(); + void cm_climit_fcn() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_ILIMIT ROUTINE ===*/ + +void cm_ilimit(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + double in_offset,gain,r_out_source,r_out_sink,i_limit_source, + i_limit_sink,v_pwr_range,i_source_range,i_sink_range, + r_out_domain,out_lower_limit,out_upper_limit,veq,pveq_pvin, + pveq_pvpos,pveq_pvneg,r_out,pr_out_px,i_out,i_threshold_lower, + i_threshold_upper,i_pos_pwr,pi_out_pvin,pi_pos_pvneg, + pi_pos_pvpos,pi_pos_pvout,i_neg_pwr,pi_neg_pvin,pi_neg_pvneg, + pi_neg_pvpos,pi_neg_pvout,vout,pi_out_plimit,pi_out_pvout, + pi_out_ppos_pwr,pi_out_pneg_pwr,pi_pos_pvin,pi_neg_plimit, + pi_pos_plimit,pos_pwr_in,neg_pwr_in; + + Mif_Complex_t ac_gain; + + + + + /* Retrieve frequently used parameters... */ + + in_offset = PARAM(in_offset); + gain = PARAM(gain); + r_out_source = PARAM(r_out_source); + r_out_sink = PARAM(r_out_sink); + i_limit_source = PARAM(i_limit_source); + i_limit_sink = PARAM(i_limit_sink); + v_pwr_range = PARAM(v_pwr_range); + i_source_range = PARAM(i_source_range); + i_sink_range = PARAM(i_sink_range); + r_out_domain = PARAM(r_out_domain); + + + + + + /* Retrieve frequently used inputs... */ + + vout = INPUT(out); + + + + /* Test to see if pos_pwr or neg_pwr are connected... */ + /* if not, assign large voltage values to the variables */ + /* pos_pwr andneg_pwr... */ + + if ( PORT_NULL(pos_pwr) ) { + pos_pwr_in = 1.0e6; + } + else { + pos_pwr_in = INPUT(pos_pwr); + } + + if ( PORT_NULL(neg_pwr) ) { + neg_pwr_in = -1.0e6; + } + else { + neg_pwr_in = INPUT(neg_pwr); + } + + + /* Compute Veq plus derivatives using climit_fcn */ + + if(INIT != 1){ + /* If reasonable power and voltage values exist (i.e., not INIT)... */ + /* then calculate expected equivalent voltage values and derivs. */ + + cm_climit_fcn(INPUT(in), in_offset, pos_pwr_in, neg_pwr_in, + 0.0, 0.0, v_pwr_range, gain, MIF_FALSE, &veq, + &pveq_pvin, &pveq_pvneg, &pveq_pvpos); + } + else { + /* Initialization pass...set nominal values */ + + veq = (pos_pwr_in - neg_pwr_in) / 2.0; + pveq_pvin = 0.0; + pveq_pvpos = 0.0; + pveq_pvneg = 0.0; + } + + + /* Calculate Rout */ + + if (r_out_source == r_out_sink) { + /* r_out constant => no calculation necessary */ + + r_out = r_out_source; + pr_out_px = 0.0; + + } + else { /* Interpolate smoothly between sourcing & sinking values */ + cm_smooth_discontinuity(veq - vout, -r_out_domain, r_out_sink, r_out_domain, + r_out_source, &r_out, &pr_out_px); + } + + + + /* Calculate i_out & derivatives */ + + i_threshold_lower = -i_limit_sink + i_sink_range; + i_threshold_upper = i_limit_source - i_source_range; + + i_out = (veq - vout) / r_out; + pi_out_pvin = (pveq_pvin/r_out - veq*pr_out_px*pveq_pvin/ + (r_out*r_out)); + pi_out_pvout = (-1.0/r_out - vout*pr_out_px/(r_out*r_out)); + + pi_out_ppos_pwr = (pveq_pvpos/r_out - veq*pr_out_px*pveq_pvpos/ + (r_out*r_out)); + pi_out_pneg_pwr = (pveq_pvneg/r_out - veq*pr_out_px*pveq_pvneg/ + (r_out*r_out)); + + + /* Preset i_pos_pwr & i_neg_pwr & partials to 0.0 */ + + i_pos_pwr = 0.0; + pi_pos_pvin = 0.0; + pi_pos_pvneg = 0.0; + pi_pos_pvpos = 0.0; + pi_pos_pvout = 0.0; + + + i_neg_pwr = 0.0; + pi_neg_pvin = 0.0; + pi_neg_pvneg = 0.0; + pi_neg_pvpos = 0.0; + pi_neg_pvout = 0.0; + + + + + /* Determine operating point of i_out for limiting */ + + if (i_out < 0.0) { /* i_out sinking */ + if (i_out < i_threshold_lower) { + if (i_out < (-i_limit_sink-i_sink_range)) { /* i_out lower-limited */ + i_out = -i_limit_sink; + i_neg_pwr = -i_out; + pi_out_pvin = 0.0; + pi_out_pvout = 0.0; + pi_out_ppos_pwr = 0.0; + pi_out_pneg_pwr = 0.0; + } + else { /* i_out in lower smoothing region */ + cm_smooth_corner(i_out,-i_limit_sink,-i_limit_sink,i_sink_range, + 0.0,1.0,&i_out,&pi_out_plimit); + pi_out_pvin = pi_out_pvin * pi_out_plimit; + pi_out_pvout = pi_out_pvout * pi_out_plimit; + pi_out_ppos_pwr = pi_out_ppos_pwr * pi_out_plimit; + pi_out_pneg_pwr = pi_out_pneg_pwr * pi_out_plimit; + + i_neg_pwr = -i_out; + pi_neg_pvin = -pi_out_pvin; + pi_neg_pvneg = -pi_out_pneg_pwr; + pi_neg_pvpos = -pi_out_ppos_pwr; + pi_neg_pvout = -pi_out_pvout; + } + } + else { /* i_out in lower linear region...calculate i_neg_pwr */ + if (i_out > -2.0*i_sink_range) { /* i_out near 0.0...smooth i_neg_pwr */ + cm_smooth_corner(i_out,-i_sink_range,0.0,i_sink_range,1.0,0.0, + &i_neg_pwr,&pi_neg_plimit); + i_neg_pwr = -i_neg_pwr; + pi_neg_pvin = -pi_out_pvin * pi_neg_plimit; + pi_neg_pvneg = -pi_out_pneg_pwr * pi_neg_plimit; + pi_neg_pvpos = -pi_out_ppos_pwr * pi_neg_plimit; + pi_neg_pvout = -pi_out_pvout * pi_neg_plimit; + } + else { + i_neg_pwr = -i_out; /* Not near i_out=0.0 => i_neg_pwr=-i_out */ + pi_neg_pvin = -pi_out_pvin; + pi_neg_pvneg = -pi_out_pneg_pwr; + pi_neg_pvpos = -pi_out_ppos_pwr; + pi_neg_pvout = -pi_out_pvout; + } + } + } + else { /* i_out sourcing */ + if (i_out > i_threshold_upper) { + if (i_out > (i_limit_source + i_source_range)) { /* i_out upper-limited */ + i_out = i_limit_source; + i_pos_pwr = -i_out; + pi_out_pvin = 0.0; + pi_out_pvout = 0.0; + pi_out_ppos_pwr = 0.0; + pi_out_pneg_pwr = 0.0; + } + else { /* i_out in upper smoothing region */ + cm_smooth_corner(i_out,i_limit_source,i_limit_source,i_sink_range, + 1.0,0.0,&i_out,&pi_out_plimit); + pi_out_pvin = pi_out_pvin * pi_out_plimit; + pi_out_pvout = pi_out_pvout * pi_out_plimit; + pi_out_ppos_pwr = pi_out_ppos_pwr * pi_out_plimit; + pi_out_pneg_pwr = pi_out_pneg_pwr * pi_out_plimit; + + i_pos_pwr = -i_out; + pi_pos_pvin = -pi_out_pvin; + pi_pos_pvneg = -pi_out_pneg_pwr; + pi_pos_pvpos = -pi_out_ppos_pwr; + pi_pos_pvout = -pi_out_pvout; + } + } + else { /* i_out in upper linear region...calculate i_pos_pwr */ + if (i_out < 2.0*i_source_range) { /* i_out near 0.0...smooth i_pos_pwr */ + cm_smooth_corner(i_out,i_source_range,0.0,i_source_range,0.0,1.0, + &i_pos_pwr,&pi_pos_plimit); + i_pos_pwr = -i_pos_pwr; + pi_pos_pvin = -pi_out_pvin * pi_pos_plimit; + pi_pos_pvneg = -pi_out_pneg_pwr * pi_pos_plimit; + pi_pos_pvpos = -pi_out_ppos_pwr * pi_pos_plimit; + pi_pos_pvout = -pi_out_pvout * pi_pos_plimit; + } + else { /* Not near i_out=0.0 => i_pos_pwr=-i_out */ + i_pos_pwr = -i_out; + pi_pos_pvin = -pi_out_pvin; + pi_pos_pvneg = -pi_out_pneg_pwr; + pi_pos_pvpos = -pi_out_ppos_pwr; + pi_pos_pvout = -pi_out_pvout; + } + } + } + + + + + + if (ANALYSIS != MIF_AC) { /* DC & Transient Analyses */ + + + /* Debug line...REMOVE FOR FINAL VERSION!!! */ + /*OUTPUT(t1) = veq; + OUTPUT(t2) = r_out; + OUTPUT(t3) = pveq_pvin; + OUTPUT(t4) = pveq_pvpos; + OUTPUT(t5) = pveq_pvneg;*/ + + + OUTPUT(out) = -i_out; /* Remember...current polarity must be */ + PARTIAL(out,in) = -pi_out_pvin; /* reversed for SPICE...all previous code */ + PARTIAL(out,out) = -pi_out_pvout; /* assumes i_out positive when EXITING */ + /* the model and negative when entering. */ + /* SPICE assumes the opposite, so a */ + /* minus sign is added to all currents */ + /* and current partials to compensate for */ + /* this fact.... JPM */ + + if ( !PORT_NULL(neg_pwr) ) { + OUTPUT(neg_pwr) = -i_neg_pwr; + PARTIAL(neg_pwr,in) = -pi_neg_pvin; + PARTIAL(neg_pwr,out) = -pi_neg_pvout; + if(!PORT_NULL(pos_pwr)){ + PARTIAL(neg_pwr,pos_pwr) = -pi_neg_pvpos; + } + PARTIAL(neg_pwr,neg_pwr) = -pi_neg_pvneg; + PARTIAL(out,neg_pwr) = -pi_out_pneg_pwr; + } + + if ( !PORT_NULL(pos_pwr) ) { + OUTPUT(pos_pwr) = -i_pos_pwr; + PARTIAL(pos_pwr,in) = -pi_pos_pvin; + PARTIAL(pos_pwr,out) = -pi_pos_pvout; + PARTIAL(pos_pwr,pos_pwr) = -pi_pos_pvpos; + if ( !PORT_NULL(neg_pwr) ) { + PARTIAL(pos_pwr,neg_pwr) = -pi_pos_pvneg; + } + PARTIAL(out,pos_pwr) = -pi_out_ppos_pwr; + } + + } + else { /* AC Analysis */ + ac_gain.real = -pi_out_pvin; + ac_gain.imag= 0.0; + AC_GAIN(out,in) = ac_gain; + + ac_gain.real = -pi_out_pvout; + ac_gain.imag= 0.0; + AC_GAIN(out,out) = ac_gain; + + if ( !PORT_NULL(neg_pwr) ) { + ac_gain.real = -pi_neg_pvin; + ac_gain.imag= 0.0; + AC_GAIN(neg_pwr,in) = ac_gain; + + ac_gain.real = -pi_out_pneg_pwr; + ac_gain.imag= 0.0; + AC_GAIN(out,neg_pwr) = ac_gain; + + ac_gain.real = -pi_neg_pvout; + ac_gain.imag= 0.0; + AC_GAIN(neg_pwr,out) = ac_gain; + + ac_gain.real = -pi_neg_pvpos; + ac_gain.imag= 0.0; + AC_GAIN(neg_pwr,pos_pwr) = ac_gain; + + ac_gain.real = -pi_neg_pvneg; + ac_gain.imag= 0.0; + AC_GAIN(neg_pwr,neg_pwr) = ac_gain; + } + + + if ( !PORT_NULL(pos_pwr) ) { + ac_gain.real = -pi_pos_pvin; + ac_gain.imag= 0.0; + AC_GAIN(pos_pwr,in) = ac_gain; + + ac_gain.real = -pi_out_ppos_pwr; + ac_gain.imag= 0.0; + AC_GAIN(out,pos_pwr) = ac_gain; + + ac_gain.real = -pi_pos_pvout; + ac_gain.imag= 0.0; + AC_GAIN(pos_pwr,out) = ac_gain; + + ac_gain.real = -pi_pos_pvpos; + ac_gain.imag= 0.0; + AC_GAIN(pos_pwr,pos_pwr) = ac_gain; + + ac_gain.real = -pi_pos_pvneg; + ac_gain.imag= 0.0; + AC_GAIN(pos_pwr,neg_pwr) = ac_gain; + } + } +} + + + + + diff --git a/src/xspice/icm/analog/ilimit/ifspec.ifs b/src/xspice/icm/analog/ilimit/ifspec.ifs new file mode 100644 index 000000000..cdf8e6928 --- /dev/null +++ b/src/xspice/icm/analog/ilimit/ifspec.ifs @@ -0,0 +1,110 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog ilimit code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_ilimit +Spice_Model_Name: ilimit +Description: "current limiter block" + + +PORT_TABLE: + + +Port_Name: in pos_pwr +Description: "input" "positive power supply" +Direction: in inout +Default_Type: v g +Allowed_Types: [v,vd,i,id,vnam] [g,gd] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no yes + +PORT_TABLE: + +Port_Name: neg_pwr out +Description: "negative power supply" "output" +Direction: inout inout +Default_Type: g g +Allowed_Types: [g,gd] [g,gd] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes no + + +PARAMETER_TABLE: + +Parameter_Name: in_offset gain +Description: "input offset" "gain" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + + +Parameter_Name: r_out_source r_out_sink +Description: "sourcing resistance" "sinking resistance" +Data_Type: real real +Default_Value: 1.0 1.0 +Limits: [1e-9 1e9] [1e-9 1e9] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + + +Parameter_Name: i_limit_source i_limit_sink +Description: "current sourcing limit" "current sinking limit" +Data_Type: real real +Default_Value: 10.0e-3 10.0e-3 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: v_pwr_range i_source_range +Description: "pwr. smoothing range" "sourcing cur sm. rng" +Data_Type: real real +Default_Value: 1e-6 1e-9 +Limits: [1e-15 -] [1e-15 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: i_sink_range r_out_domain +Description: "sinking cur sm. rng" "output resistance sm. domain" +Data_Type: real real +Default_Value: 1e-9 1e-9 +Limits: [1e-15 -] [1e-15 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes diff --git a/src/xspice/icm/analog/int/cfunc.mod b/src/xspice/icm/analog/int/cfunc.mod new file mode 100644 index 000000000..13e5d9db3 --- /dev/null +++ b/src/xspice/icm/analog/int/cfunc.mod @@ -0,0 +1,242 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE int/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 Nov 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the int code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_integrate() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include "int.h" + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_int() + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + This function implements the int code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_integrate() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_INT ROUTINE ===*/ + +void cm_int(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + double *out, /* current output */ + *in, /* input */ + in_offset, /* input offset */ + gain, /* gain parameter */ + out_lower_limit, /* output lower limit */ + out_upper_limit, /* output upper limit */ + limit_range, /* range of output below out_upper_limit + and above out_lower_limit within which + smoothing will take place */ + out_ic, /* output initial condition - initial output value */ + pout_pin, /* partial derivative of output w.r.t. input */ + pout_gain; /* temporary storage variable for partial + value returned by smoothing function + (subsequently multiplied by pout_pin) */ + + Mif_Complex_t ac_gain; /* AC gain */ + + + + /** Retrieve frequently used parameters (used by all analyses)... **/ + + gain = PARAM(gain); + + + + if (ANALYSIS != MIF_AC) { /**** DC & Transient Analyses ****/ + + /** Retrieve frequently used parameters... **/ + + in_offset = PARAM(in_offset); + out_lower_limit = PARAM(out_lower_limit); + out_upper_limit = PARAM(out_upper_limit); + limit_range = PARAM(limit_range); + out_ic = PARAM(out_ic); + + + + /** Test for INIT; if so, allocate storage, otherwise, retrieve + previous timepoint input value... **/ + + if (INIT==1) { /* First pass...allocate storage for previous value. */ + + in = cm_analog_alloc(INT1,sizeof(double)); + out = cm_analog_alloc(INT2,sizeof(double)); + } + else { /* Allocation not necessary...retrieve previous value */ + + in = cm_analog_get_ptr(INT1,0); /* Set out pointer to input storage location */ + out = cm_analog_get_ptr(INT2,0); /* Set out pointer to output storage location */ + } + + + /*** Read input value for current time, and calculate pseudo-input ***/ + /*** which includes input offset and gain.... ***/ + + *in = gain*(INPUT(in)+in_offset); + + /*** Test to see if this is the first timepoint calculation... ***/ + /*** this would imply that TIME equals zero. ***/ + + if ( 0.0 == TIME ) { /*** Test to see if this is the first ***/ + /*** timepoint calculation...if ***/ + *out = out_ic; /*** so, return out_ic. ***/ + pout_pin = 0.0; + } + else { /*** Calculate value of integral.... ***/ + cm_analog_integrate(*in,out,&pout_pin); + } + + + /*** Smooth output if it is within limit_range of + out_lower_limit or out_upper_limit. ***/ + + if (*out < (out_lower_limit - limit_range)) { /* At lower limit. */ + *out = out_lower_limit; + pout_pin = 0.0; + } + else { + if (*out < (out_lower_limit + limit_range)) { /* Lower smoothing range */ + cm_smooth_corner(*out,out_lower_limit,out_lower_limit,limit_range, + 0.0,1.0,out,&pout_gain); + pout_pin = pout_pin * pout_gain; + } + else { + if (*out > (out_upper_limit + limit_range)) { /* At upper limit */ + *out = out_upper_limit; + pout_pin = 0.0; + } + else { + if (*out > (out_upper_limit - limit_range)) { /* Upper smoothing region */ + cm_smooth_corner(*out,out_upper_limit,out_upper_limit,limit_range, + 1.0,0.0,out,&pout_gain); + pout_pin = pout_pin * pout_gain; + } + } + } + } + + + + + /** Output values for DC & Transient **/ + + OUTPUT(out) = *out; + PARTIAL(out,in) = pout_pin; + + } + + else { /**** AC Analysis...output (0.0,gain/s) ****/ + ac_gain.real = 0.0; + ac_gain.imag = -gain / RAD_FREQ; + AC_GAIN(out,in) = ac_gain; + } +} + + + + + diff --git a/src/xspice/icm/analog/int/ifspec.ifs b/src/xspice/icm/analog/int/ifspec.ifs new file mode 100644 index 000000000..daa7631fa --- /dev/null +++ b/src/xspice/icm/analog/int/ifspec.ifs @@ -0,0 +1,79 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 6 Nov 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog int code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_int +Spice_Model_Name: int +Description: "integrator block" + + +PORT_TABLE: + + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + + +Parameter_Name: in_offset gain +Description: "input offset" "gain" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + + +Parameter_Name: out_lower_limit out_upper_limit +Description: "output lower limit" "output upper limit" +Data_Type: real real +Default_Value: - - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + + +Parameter_Name: limit_range out_ic +Description: "upper & lower sm. range" "output initial condition" +Data_Type: real real +Default_Value: 1.0e-6 0.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + diff --git a/src/xspice/icm/analog/int/int.h b/src/xspice/icm/analog/int/int.h new file mode 100644 index 000000000..74abdcf38 --- /dev/null +++ b/src/xspice/icm/analog/int/int.h @@ -0,0 +1,75 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE int/int.h + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 Nov 1990 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains additional header information for + the int code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + +REFERENCED FILES + + NONE + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + +#define INT1 1 +#define INT2 2 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + diff --git a/src/xspice/icm/analog/limit/cfunc.mod b/src/xspice/icm/analog/limit/cfunc.mod new file mode 100644 index 000000000..ede8ea64a --- /dev/null +++ b/src/xspice/icm/analog/limit/cfunc.mod @@ -0,0 +1,203 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE limit/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the limit code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_limit() + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + This function implements the limit code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_LIMIT ROUTINE ===*/ + +void cm_limit(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + double out_lower_limit; /* output lower limit */ + double out_upper_limit; /* output upper limit */ + double limit_range; /* upper and lower limit smoothing range */ + double gain; /* gain */ + double threshold_upper; /* value above which smoothing takes place */ + double threshold_lower; /* value below which smoothing takes place */ + double out; /* output */ + double limited_out; /* limited output value */ + double out_partial; /* partial of the output wrt input */ + + Mif_Complex_t ac_gain; + + + + /* Retrieve frequently used parameters... */ + + out_lower_limit = PARAM(out_lower_limit); + out_upper_limit = PARAM(out_upper_limit); + limit_range = PARAM(limit_range); + gain = PARAM(gain); + + + if (PARAM(fraction) == MIF_TRUE) /* Set range to absolute value */ + limit_range = limit_range * + (out_upper_limit - out_lower_limit); + + + + threshold_upper = out_upper_limit - /* Set Upper Threshold */ + limit_range; + + threshold_lower = out_lower_limit + /* Set Lower Threshold */ + limit_range; + + + + /* Compute Un-Limited Output */ + + out = gain * (PARAM(in_offset) + INPUT(in)); + + + + if (out < threshold_lower) { /* Limit Out @ Lower Bound */ + + if (out > (out_lower_limit - limit_range)) { /* Parabolic */ + cm_smooth_corner(out,out_lower_limit,out_lower_limit, + limit_range,0.0,1.0,&limited_out, + &out_partial); + out_partial = gain * out_partial; + } + else { /* Hard-Limited Region */ + limited_out = out_lower_limit; + out_partial = 0.0; + } + } + else { + if (out > threshold_upper) { /* Limit Out @ Upper Bound */ + + if (out < (out_upper_limit + limit_range)) { /* Parabolic */ + cm_smooth_corner(out,out_upper_limit,out_upper_limit, + limit_range,1.0,0.0,&limited_out, + &out_partial); + out_partial = gain * out_partial; + } + else { /* Hard-Limited Region */ + limited_out = out_upper_limit; + out_partial = 0.0; + } + } + else { /* No Limiting Needed */ + limited_out = out; + out_partial = gain; + } + } + + if (ANALYSIS != MIF_AC) { /* DC & Transient Analyses */ + + OUTPUT(out) = limited_out; + PARTIAL(out,in) = out_partial; + + } + else { /* AC Analysis */ + ac_gain.real = out_partial; + ac_gain.imag= 0.0; + AC_GAIN(out,in) = ac_gain; + + } +} diff --git a/src/xspice/icm/analog/limit/ifspec.ifs b/src/xspice/icm/analog/limit/ifspec.ifs new file mode 100644 index 000000000..543321453 --- /dev/null +++ b/src/xspice/icm/analog/limit/ifspec.ifs @@ -0,0 +1,80 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog limit code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_limit +Spice_Model_Name: limit +Description: "limit block" + + +PORT_TABLE: + + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + + +Parameter_Name: in_offset gain +Description: "input offset" "gain" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + + +Parameter_Name: out_lower_limit out_upper_limit +Description: "output lower limit" "output upper limit" +Data_Type: real real +Default_Value: - - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + + +Parameter_Name: limit_range fraction +Description: "upper & lower sm. range" "smoothing percent/abs switch" +Data_Type: real boolean +Default_Value: 1.0e-6 FALSE +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + diff --git a/src/xspice/icm/analog/modpath.lst b/src/xspice/icm/analog/modpath.lst new file mode 100644 index 000000000..c38a4aff5 --- /dev/null +++ b/src/xspice/icm/analog/modpath.lst @@ -0,0 +1,18 @@ +climit +divide +d_dt +gain +hyst +ilimit +int +limit +mult +oneshot +pwl +sine +slew +square +summer +s_xfer +triangle + diff --git a/src/xspice/icm/analog/mult/cfunc.mod b/src/xspice/icm/analog/mult/cfunc.mod new file mode 100644 index 000000000..b4c108f88 --- /dev/null +++ b/src/xspice/icm/analog/mult/cfunc.mod @@ -0,0 +1,179 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE mult/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 20 Mar 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the mult code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_mult() + +AUTHORS + + 20 Mar 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the mult code model. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_MULT ROUTINE ===*/ + + +void cm_mult(ARGS) + +{ + int i; /* generic loop counter index */ + int size; /* number of input ports */ + + double accumulate_gain; /* product of all the gains */ + double accumulate_in; /* product of all (inputs + offsets) */ + double final_gain; /* output gain */ + + Mif_Complex_t ac_gain; + + + size = PORT_SIZE(in); /* Note that port size */ + final_gain = PARAM(out_gain); /* and out_gain are read only */ + /* once...saves access time. */ + + + /* Calculate multiplication of inputs and gains for */ + /* all types of analyes.... */ + + accumulate_gain = 1.0; + accumulate_in = 1.0; + + for (i=0; i :\ +* / : : : \ +* <---rise_delay--> / : :<-fall_delay->: \ +* ___|________________/ : : : \____________ +* ^ <-->: : :<--> +* Trigger Risetime Falltime +* +* +****************************************************************************************/ + +void cm_oneshot(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + int i; /* generic loop counter index */ + int *locked; /* pointer used to store the locked1 variable */ + int locked1; /* flag which allows the time points to be + reset. value determined by retrig parameter */ + int cntl_size; /* size of the control array */ + int pw_size; /* size of the pulse-width array */ + int *state; /* pointer used to store state1 variable */ + int state1; /* if state1 = 1, then oneshot has + been triggered. if state1 = 0, no change */ + int *set; /* pointer used to store the state of set1 */ + int set1; /* flag used to set/reset the oneshot */ + int trig_pos_edge; /* flag used to define positive or negative + edge triggering. 1=positive, 0=negative */ + + double *x; /* pointer used to store the control array */ + double *y; /* pointer used to store the pulse-width array */ + double cntl_input; /* the actual value of the control input */ + double out; /* value of the output */ + double dout_din; /* slope of the pw wrt the control voltage */ + double output_low; /* output low value */ + double output_hi; /* output high value */ + double pw; /* actual value of the pulse-width */ +/* double del_out; value of the delay time between triggering + and a change in the output */ + double del_rise; /* value of the delay time between triggering + and a change in the output */ + double del_fall; /* value of the delay time between the end of the + pw and a change in the output */ + double *t1; /* pointer used to store time1 */ + double *t2; /* pointer used to store time2 */ + double *t3; /* pointer used to store time3 */ + double *t4; /* pointer used to store time4 */ + double time1; /* time at which the output first begins to + change (trigger + delay) */ + double time2; /* time2 = time1 + risetime */ + double time3; /* time3 = time2 + pw */ + double time4; /* time4 = time3 + falltime */ + double t_rise; /* risetime */ + double t_fall; /* falltime */ + double *output_old;/* pointer which stores the previous output */ + double *clock; /* pointer which stores the clock */ + double *old_clock; /* pointer which stores the previous clock */ + double trig_clk; /* value at which the clock triggers the oneshot */ + + Mif_Complex_t ac_gain; + + + /**** Retrieve frequently used parameters... ****/ + + cntl_size = PARAM_SIZE(cntl_array); + pw_size = PARAM_SIZE(pw_array); + trig_clk = PARAM(clk_trig); + trig_pos_edge = PARAM(pos_edge_trig); + output_low = PARAM(out_low); + output_hi = PARAM(out_high); + /*del_out = PARAM(delay);*/ + del_rise = PARAM(rise_delay); + del_fall = PARAM(fall_delay); + t_rise = PARAM(rise_time); + t_fall = PARAM(fall_time); + + /* set minimum rise and fall_times */ + + if(t_rise < 1e-12){ + t_rise = 1e-12; + } + + if(t_fall < 1e-12){ + t_fall = 1e-12; + } + + /* the control array must be the same size as the pulse-width array */ + + if(cntl_size != pw_size){ + cm_message_send(oneshot_array_error); + return; + } + + if(INIT == 1){ /* first time through, allocate memory */ + + t1 = cm_analog_alloc(T1,sizeof(double)); + t2 = cm_analog_alloc(T2,sizeof(double)); + t3 = cm_analog_alloc(T3,sizeof(double)); + t4 = cm_analog_alloc(T4,sizeof(double)); + set = cm_analog_alloc(SET,sizeof(int)); + state = cm_analog_alloc(STATE,sizeof(int)); + clock = cm_analog_alloc(CLOCK,sizeof(double)); + locked = cm_analog_alloc(LOCKED,sizeof(int)); + output_old = cm_analog_alloc(OUTPUT_OLD,sizeof(double)); + + } + + if(ANALYSIS == MIF_DC){ + + /* for DC, initialize values and set the output = output_low */ + + t1 = cm_analog_get_ptr(T1,0); + t2 = cm_analog_get_ptr(T2,0); + t3 = cm_analog_get_ptr(T3,0); + t4 = cm_analog_get_ptr(T4,0); + set = cm_analog_get_ptr(SET,0); + state = cm_analog_get_ptr(STATE,0); + locked = cm_analog_get_ptr(LOCKED,0); + output_old = cm_analog_get_ptr(OUTPUT_OLD,0); + + /* initialize time and state values */ + *t1 = -1; + *t2 = -1; + *t3 = -1; + *t4 = -1; + *set = 0; + *locked = 0; + *state = 0; + *output_old = output_low; + + OUTPUT(out) = output_low; + if(PORT_NULL(cntl_in) != 1){ + PARTIAL(out,cntl_in) = 0; + } + if(PORT_NULL(clear) != 1){ + PARTIAL(out,clear) = 0; + } + PARTIAL(out,clk) = 0; + + }else + + if(ANALYSIS == MIF_TRAN){ + +/* retrieve previous values, set them equal to the variables + Note that these pointer values are immediately dumped into + other variables because the previous values can't change- + can't rewrite the old values */ + + t1 = cm_analog_get_ptr(T1,1); + t2 = cm_analog_get_ptr(T2,1); + t3 = cm_analog_get_ptr(T3,1); + t4 = cm_analog_get_ptr(T4,1); + set = cm_analog_get_ptr(SET,1); + state = cm_analog_get_ptr(STATE,1); + locked = cm_analog_get_ptr(LOCKED,1); + clock = cm_analog_get_ptr(CLOCK,0); + old_clock = cm_analog_get_ptr(CLOCK,1); + output_old = cm_analog_get_ptr(OUTPUT_OLD,1); + + time1 = *t1; + time2 = *t2; + time3 = *t3; + time4 = *t4; + set1 = *set; + state1 = *state; + locked1 = *locked; + +if((PORT_NULL(clear) != 1) && (INPUT(clear) > trig_clk)){ + + time1 = -1; + time2 = -1; + time3 = -1; + time4 = -1; + set1 = 0; + locked1 = 0; + state1 = 0; + + OUTPUT(out) = output_low; + + +}else{ + + /* Allocate storage for breakpoint domain & freq. range values */ + + x = (double *) calloc(cntl_size, sizeof(double)); + if (x == '\0') { + cm_message_send(oneshot_allocation_error); + return; + } + + y = (double *) calloc(pw_size, sizeof(double)); + if (y == '\0') { + cm_message_send(oneshot_allocation_error); + return; + } + + + /* Retrieve control and pulse-width values. */ + for (i=0; i= *(x+cntl_size-1)){ + dout_din = (*(y+cntl_size-1) - *(y+cntl_size-2)) / + (*(x+cntl_size-1) - *(x+cntl_size-2)); + pw = *(y+cntl_size-1) + (cntl_input - *(x+cntl_size-1)) * dout_din; + + } else { /*** cntl_input within bounds of end midpoints... + must determine position progressively & then + calculate required output. ***/ + + for (i=0; i= *(x+i))){ + + /* Interpolate to get the correct pulse width value */ + + pw = ((cntl_input - *(x+i))/(*(x+i+1) - *(x+i)))* + (*(y+i+1)-*(y+i)) + *(y+i); + } + + } + } + + +if(trig_pos_edge){ /* for a positive edge trigger */ + + if(!set1){ /* if set1=0, then look for + 1. a rising edge trigger + 2. the clock to be higher than the trigger value */ + + if((*clock > *old_clock) && (*clock > trig_clk)){ + + state1 = 1; + set1 = 1; + + } + + }else + + /* look for a neg edge before resetting the trigger */ + + if((*clock < *old_clock) && (*clock < trig_clk)){ + + set1 = 0; + + } + +}else{ + /* This stuff belongs to the case where a negative edge + is needed */ + + if(!set1){ + + if((*clock < *old_clock) && (*clock < trig_clk)){ + + state1 = 1; + set1 = 1; + + } + + }else + /* look for a pos edge before resetting the trigger */ + + if((*clock > *old_clock) && (*clock > trig_clk)){ + + set1 = 0; + } +} + + + /* I can only set the breakpoints if the state1 is high and + the output is low, and locked = 0 */ + if((state1) && (*output_old - output_low < 1e-20) && (!locked1)){ + +/* if state1 is 1, and the output is low, then set the time points + and the temporary breakpoints */ + + time1 = TIME + del_rise; + time2 = time1 + t_rise; + time3 = time2 + pw + del_fall; + time4 = time3 + t_fall; + + if(PARAM(retrig) == MIF_FALSE){ + + locked1 = 1; + + } + + if((TIME < time1) || (T(1) == 0)){ + cm_analog_set_temp_bkpt(time1); + } + + cm_analog_set_temp_bkpt(time2); + cm_analog_set_temp_bkpt(time3); + cm_analog_set_temp_bkpt(time4); + + /* reset the state value */ + state1 = 0; + OUTPUT(out) = output_low; + + }else + + /* state1 = 1, and the output is high, then just set time3 and time4 + and their temporary breakpoints This implies that the oneshot was + retriggered */ + + if((state1) && (*output_old - output_hi < 1e-20) && (!locked1)){ + + time3 = TIME + pw + del_rise + del_fall + t_rise; + time4 = time3 + t_fall; + + cm_analog_set_temp_bkpt(time3); + cm_analog_set_temp_bkpt(time4); + + OUTPUT(out) = output_hi; + + state1 = 0; + + } + +/* reset the state if it's 1 and the locked flag is 1. This + means that the clock tried to retrigger the oneshot, but + the retrig flag prevented it from doing so */ + + if((state1) && (locked1)){ + + state1 = 0; + + } + /* set the value for the output depending on the current time, and + the values of time1, time2, time3, and time4 */ + if(TIME < time1){ + + OUTPUT(out) = output_low; + + }else + if((time1 <= TIME) && (TIME < time2)){ + + OUTPUT(out) = output_low + ((TIME - time1)/(time2 - time1))* + (output_hi - output_low); + + }else + if((time2 <= TIME) && (TIME < time3)){ + + OUTPUT(out) = output_hi; + + }else + if((time3 <= TIME) && (TIME < time4)){ + + OUTPUT(out) = output_hi + ((TIME - time3)/(time4 - time3))* + (output_low - output_hi); + + }else{ + + + OUTPUT(out) = output_low; + + /* oneshot can now be retriggered, set locked to 0 */ + if(PARAM(retrig) == MIF_FALSE){ + + locked1 = 0; + + } + } + + /* set the variables which need to be stored for the next iteration */ + } + t1 = cm_analog_get_ptr(T1,0); + t2 = cm_analog_get_ptr(T2,0); + t3 = cm_analog_get_ptr(T3,0); + t4 = cm_analog_get_ptr(T4,0); + set = cm_analog_get_ptr(SET,0); + locked = cm_analog_get_ptr(LOCKED,0); + state = cm_analog_get_ptr(STATE,0); + output_old = cm_analog_get_ptr(OUTPUT_OLD,0); + + *t1 = time1; + *t2 = time2; + *t3 = time3; + *t4 = time4; + *set = set1; + *state = state1; + *output_old = OUTPUT(out); + *locked = locked1; + + if(PORT_NULL(cntl_in) != 1){ + PARTIAL(out,cntl_in) = 0; + } + if(PORT_NULL(clear) != 1){ + PARTIAL(out,clear) = 0; + } + PARTIAL(out,clk) = 0 ; + + } else { /* Output AC Gain */ + + /* This model has no AC capability */ + + ac_gain.real = 0.0; + ac_gain.imag= 0.0; + AC_GAIN(out,clk) = ac_gain; + } +} + diff --git a/src/xspice/icm/analog/oneshot/ifspec.ifs b/src/xspice/icm/analog/oneshot/ifspec.ifs new file mode 100644 index 000000000..4457286e8 --- /dev/null +++ b/src/xspice/icm/analog/oneshot/ifspec.ifs @@ -0,0 +1,117 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 20 Mar 1991 Harry Li + + +SUMMARY + + This file contains the interface specification file for the + analog oneshot code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_oneshot +Spice_Model_Name: oneshot +Description: "one-shot" + + +PORT_TABLE: + +Port_Name: clk cntl_in +Description: "clock input" "input" +Direction: in in +Default_Type: v v +Allowed_Types: [v,vd,vnam,i,id] [v,vnam,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no yes + +PORT_TABLE: + +Port_Name: clear out +Description: "clear signal" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,vnam,i,id] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes no + +PARAMETER_TABLE: + +Parameter_Name: cntl_array pw_array +Description: "control in array" "pulse width array" +Data_Type: real real +Default_Value: 0.0 1.0e-6 +Limits: - [0 -] +Vector: yes yes +Vector_Bounds: [2 -] [2 -] +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: clk_trig pos_edge_trig +Description: "clock trigger value" "pos/neg edge trigger switch" +Data_Type: real boolean +Default_Value: 0.5 TRUE +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: out_low out_high +Description: "output low value" "output high value" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: rise_time +Description: "output rise time" +Data_Type: real +Default_Value: 1.0e-9 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "output delay from trigger" "output delay from pw" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: fall_time retrig +Description: "output rise time" "retrigger switch" +Data_Type: real boolean +Default_Value: 1.0e-9 FALSE +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + diff --git a/src/xspice/icm/analog/oneshot/oneshot.h b/src/xspice/icm/analog/oneshot/oneshot.h new file mode 100644 index 000000000..a16f474b3 --- /dev/null +++ b/src/xspice/icm/analog/oneshot/oneshot.h @@ -0,0 +1,43 @@ +/************************************************/ +/****** Structures, etc. for pwl model. ******/ +/****** 10/10/90 JPM ******/ +/************************************************/ + + + +/**** Error Messages ****/ + +char *oneshot_allocation_error = "\n**** Error ****\nONESHOT: Error allocating oneshot block storage \n"; +char *oneshot_array_error = "\n**** Error ****\nONESHOT: Size of control array different than pulse-width array \n"; +char *oneshot_pw_clamp = "\n**** Warning ****\nONESHOT: Extrapolated Pulse-Width Limited to zero \n"; + + +#define T1 1 +#define T2 2 +#define T3 3 +#define T4 4 +#define SET 5 +#define STATE 6 +#define CLOCK 7 +#define OUTPUT_OLD 8 +#define LOCKED 9 + +/***** Define Error Messages **************************************/ + + + + + + +/***** Structure Definitions *************************************/ + + + + + + +/***** Function Definitions ***************************************/ + + + + diff --git a/src/xspice/icm/analog/pwl/cfunc.mod b/src/xspice/icm/analog/pwl/cfunc.mod new file mode 100644 index 000000000..ce1624cde --- /dev/null +++ b/src/xspice/icm/analog/pwl/cfunc.mod @@ -0,0 +1,520 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE pwl/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 19 Apr 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 25 Sep 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the pwl (piece-wise linear) code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + CMmacros.h cm_message_send(); + + CM.c void cm_analog_not_converged() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include + + + +/*=== CONSTANTS ========================*/ + +#define FRACTION 0.30 +#define EPSILON 1.0e-9 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION double limit_x_value() + +AUTHORS + + 25 Sep 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + Limits a passed input value to some fraction + of the segment length defined by + (x_upper - x_lower). The fractional value in + question is passed as a value to the routine + (fraction). + + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void cm_analog_not_converged() + + +RETURNED VALUE + + Returns a double. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static LIMIT_X_VALUE ROUTINE ================*/ + +/** limit_x_value ******************************************/ +/** **/ +/** Limits a passed input value to some fraction **/ +/** of the segment length defined by **/ +/** (x_upper - x_lower). The fractional value in **/ +/** question is passed as a value to the routine **/ +/** (fraction). **/ +/** **/ +/** 9/25/91 JPM **/ +/***********************************************************/ + +static double limit_x_value(double x_lower,double x_upper, + double x_input,double fraction, + double *last_x_value) +{ + double max_x_delta, /* maximum delta value permissible for + this segment domain. */ + hold; /* Holding variable for previous x_input value */ + + + /** Limit effective change of input to fraction of value of lowest **/ + /** x-segment length... **/ + + /* calculate maximum delta value for this region */ + max_x_delta = fraction * (x_upper - x_lower); + + /* Test new input */ + if ( max_x_delta < fabs(x_input - *last_x_value) ) { + + hold = x_input; + + /* Assign new x_input based of direction of movement */ + /* since last iteration call */ + if ( 0.0 <= (x_input - *last_x_value) ) { + x_input = *last_x_value = *last_x_value + max_x_delta; + } + else { + x_input = *last_x_value = *last_x_value - max_x_delta; + } + + /* Alert the simulator to non-convergence */ + cm_analog_not_converged(); + + /*** Debugging printf statement ***/ + /* printf("Assigning new x_input...\nPrevious value=%e, New value=%e\n\n", + hold,x_input); + */ + + } + else { /* No limiting of x_input required */ + *last_x_value = x_input; + } + + return x_input; + +} + +/*============================================================================== + +FUNCTION void cm_pwl(> + +AUTHORS + + 19 Apr 1991 Jeffrey P. Murray + +MODIFICATIONS + + 25 Sep 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the pwl code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_smooth_corner(); + + CMmacros.h cm_message_send(); + + CM.c void cm_analog_not_converged() + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_PWL ROUTINE ================*/ + +void cm_pwl(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + int i; /* generic loop counter index */ + int size; /* size of the x_array */ + + double input_domain; /* smoothing range */ + double *x; /* pointer to the x-coordinate array */ + double *y; /* pointer to the y-coordinate array */ + double lower_seg; /* x segment below which input resides */ + double upper_seg; /* x segment above which the input resides */ + double lower_slope; /* slope of the lower segment */ + double upper_slope; /* slope of the upper segment */ + double x_input; /* input */ + double out; /* output */ + double dout_din; /* partial derivative of the output wrt input */ + double threshold_lower; /* value below which the output begins smoothing */ + double threshold_upper; /* value above which the output begins smoothing */ + double test1; /* debug testing value */ + double test2; /* debug testing value */ + double *last_x_value; /* static variable for limiting */ + double test; /* temp storage variable for limit testing */ + + Mif_Complex_t ac_gain; + + char *allocation_error="\n***ERROR***\nPWL: Allocation calloc failed!\n"; + char *limit_error="\n***ERROR***\nPWL: Violation of 50% rule in breakpoints!\n"; + + /* Retrieve frequently used parameters... */ + + input_domain = PARAM(input_domain); + + size = PARAM_SIZE(x_array); + + + + if (INIT==1) { /* First pass...allocate storage for previous value... */ + + /* Allocate storage for last_x_value */ + STATIC_VAR(last_x_value) = (double *) malloc(sizeof(double)); + last_x_value = STATIC_VAR(last_x_value); + + /* Allocate storage for breakpoint domain & range values */ + STATIC_VAR(x) = (double *) calloc(size, sizeof(double)); + x = STATIC_VAR(x); + if (x == '\0') { + cm_message_send(allocation_error); + } + + STATIC_VAR(y) = (double *) calloc(size, sizeof(double)); + y = STATIC_VAR(y); + if (y == '\0') { + cm_message_send(allocation_error); + } + + /* Retrieve x and y values. */ + for (i=0; i (x[1] - x[0]) ) { + test = limit_x_value(x_input,x[0],x_input,FRACTION,last_x_value); + } + else { + test = limit_x_value(x[0],x[1],x_input,FRACTION,last_x_value); + } + + /* If the test value is greater than x[0], force to x[0] */ + if ( test >= x[0] ) { + x_input = *last_x_value = x[0]; + + /* Alert the simulator to non-convergence */ + cm_analog_not_converged(); + } + else { + x_input = *last_x_value = test; + } + } + else + if ( *last_x_value >= x[size-1] ) { /** Non-Limited input greater than x[size-1] **/ + + /* Obtain the test value of the input, if it has changed excessively */ + if ( (x_input - x[size-1]) > (x[size-1] - x[size-2]) ) { + test = limit_x_value(x[size-1],x_input,x_input,FRACTION,last_x_value); + } + else { + test = limit_x_value(x[size-2],x[size-1],x_input,FRACTION,last_x_value); + } + + /* If the test value is less than x[size-1], force to x[size-1] */ + /* minus some epsilon value. */ + if ( test < x[size-1] ) { + x_input = *last_x_value = x[size-1] - EPSILON; + + /* Alert the simulator to non-convergence */ + cm_analog_not_converged(); + } + else { + x_input = *last_x_value = test; + } + } + else { + for (i=1; i x[i] ) { + x_input = *last_x_value = x[i]; + + /* Alert the simulator to non-convergence */ + cm_analog_not_converged(); + + break; + } + else + /* If the test value is less than x[i-1], force to x[i-1] */ + /* minus some epsilon value... */ + if ( test < x[i-1] ) { + x_input = *last_x_value = x[i-1] - EPSILON; + + /* Alert the simulator to non-convergence */ + cm_analog_not_converged(); + + break; + } + else { /* Use returned value for next input */ + x_input = *last_x_value = test; + break; + } + } + } + } + + /* Assign new limited value back to the input for */ + /* use in the matrix calculations.... */ + INPUT(in) = x_input; + + + /*** Add debugging printf statement ***/ + /* printf("Limited x_input=%e\n\n", + x_input); + */ + + + /**** End internal limiting ****/ + + + + /* Determine segment boundaries within which x_input resides */ + + if (x_input <= (x[0] + x[1])/2.0) {/*** x_input below lowest midpoint ***/ + dout_din = (y[1] - y[0])/(x[1] - x[0]); + + + /* Compute new output */ + out = y[0] + (x_input - x[0]) * dout_din; + + } + else { + if (x_input >= (x[size-2] + x[size-1])/2.0) { + /*** x_input above highest midpoint ***/ + dout_din = (y[size-1] - y[size-2]) / + (x[size-1] - x[size-2]); + + out = y[size-1] + (x_input - x[size-1]) * dout_din; + } + else { /*** x_input within bounds of end midpoints... ***/ + /*** must determine position progressively & then ***/ + /*** calculate required output. ***/ + + for (i=1; i + + + +/*=== CONSTANTS ========================*/ + + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================= + +FUNCTION cm_complex_div + +AUTHORS + + 27 Sept 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + Performs a complex division. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + A Mif_Complex_t value representing the result of the complex division. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_COMPLEX_DIV ROUTINE ===*/ + +/**** Cm_complex_div Function - FAKE ***********/ +/* */ +/* Function will not be used in finished */ +/* system...provides a stub for performing */ +/* a simple complex division. */ +/* 12/3/90 JPM */ +/* */ +/***********************************************/ + +static Mif_Complex_t cm_complex_div(Mif_Complex_t x, Mif_Complex_t y) +{ +double mag_x, phase_x, mag_y, phase_y; + +Mif_Complex_t out; + +mag_x = sqrt( (x.real * x.real) + (x.imag * x.imag) ); +phase_x = atan2(x.imag, x.real); + +mag_y = sqrt( (y.real * y.real) + (y.imag * y.imag) ); +phase_y = atan2(y.imag, y.real); + +mag_x = mag_x/mag_y; +phase_x = phase_x - phase_y; + +out.real = mag_x * cos(phase_x); +out.imag = mag_x * sin(phase_x); + +return out; +} + + + +/*============================================================================== + +FUNCTION cm_s_xfer() + +AUTHORS + + 17 Mar 1991 Jeffrey P. Murray + +MODIFICATIONS + + 18 Apr 1991 Harry Li + 27 Sept 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the s_xfer code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_integrate() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_S_XFER ROUTINE ===*/ + +/**************************************** +* S-Domain Transfer Function - * +* Code Body * +* * +* Last Modified - 9/27/91 JPM * +****************************************/ + +void cm_s_xfer(ARGS) /* structure holding parms, inputs, outputs, etc. */ +{ + double *out; /* pointer to the output */ + double *in; /* pointer to the input */ + double in_offset; /* input offset */ + double *gain; /* pointer to the gain */ + double **den_coefficient; /* dynamic array that holds the denominator + coefficients */ + double **old_den_coefficient;/* dynamic array that holds the old + denonminator coefficients */ + double **num_coefficient; /* dynamic array that holds the numerator + coefficients */ + double **old_num_coefficient;/* dynamic array that holds the old numerator + coefficients */ + double factor; /* gain factor in case the highest + denominator coefficient is not 1 */ + double **integrator; /* outputs of the integrators */ + double **old_integrator; /* previous integrator outputs */ + double null; /* dummy pointer for use with the + integrate function */ + double pout_pin; /* partial out wrt in */ + double total_gain; /* not used, currently-used with ITP stuff */ + double temp; /* temporary variable used with the + correct type of AC value */ + double frac; /* holds fractional part of a divide */ + double divide_integer; /* integer part of a modf used in AC */ + double denormalized_freq; /* denormalization constant...the nominal + corner or center frequencies specified + by the model coefficients will be + denormalized by this amount. Thus, if + coefficients were obtained which specified + a 1 rad/sec cornere frequency, specifying + a value of 1000.0 for denormalized_freq + will cause the model to shift the corner + freq. to 2.0 * pi * 1000.0 */ + double *old_gain; /* pointer to the gain if the highest order + denominator coefficient is not factored out */ + + Mif_Complex_t ac_gain, acc_num, acc_den; + + int i; /* generic loop counter index */ + int den_size; /* size of the denominator coefficient array */ + int num_size; /* size of the numerator coefficient array */ + + char *num_size_error="\n***ERROR***\nS_XFER: Numerator coefficient array size greater than\ndenominator coefficiant array size.\n"; + + + + /** Retrieve frequently used parameters (used by all analyses)... **/ + + in_offset = PARAM(in_offset); + num_size = PARAM_SIZE(num_coeff); + den_size = PARAM_SIZE(den_coeff); + if ( PARAM_NULL(denormalized_freq) ) { + denormalized_freq = 1.0; + } + else { + denormalized_freq = PARAM(denormalized_freq); + } + + if ( num_size > den_size ) { + cm_message_send(num_size_error); + return; + } + + /** Test for INIT; if so, allocate storage, otherwise, retrieve previous **/ + /** timepoint input values as necessary in subsequent analysis sections... **/ + + if (INIT==1) { /* First pass...allocate storage for previous values... */ + + /* Allocate rotational storage for integrator outputs, in & out */ + + +/***** The following two lines may be unnecessary in the final version *****/ + +/* We have to allocate memory and use cm_analog_alloc, because the ITP variables + are not functional */ + + integrator = (double **) calloc(den_size,sizeof(double *)); + old_integrator = (double **) calloc(den_size,sizeof(double *)); + + for (i=0; i0; i--) { + cm_analog_integrate(*(integrator[i]),(integrator[i-1]),&null); + } + + + + /* Calculate the output based on the new integrator values... */ + + *out = 0.0; + for (i=0; i 0.0 ) { /* Negative coefficient */ + /* values for this iteration. */ + if (frac > 0.0 ) { /** Odd Powers of "s" **/ + acc_num.imag = acc_num.imag - *(num_coefficient[i]) * pow(RAD_FREQ,i) * (*gain); + } + else { /** Even Powers of "s" **/ + acc_num.real = acc_num.real - *(num_coefficient[i]) * pow(RAD_FREQ,i) * (*gain); + } + } + else { /* Positive coefficient values for this iteration */ + if (frac> 0.0 ) { /** Odd Powers of "s" **/ + acc_num.imag = acc_num.imag + *(num_coefficient[i]) * pow(RAD_FREQ,i) * (*gain); + } + else { /** Even Powers of "s" **/ + acc_num.real = acc_num.real + *(num_coefficient[i]) * pow(RAD_FREQ,i) * (*gain); + } + } + } + + /*** Calculate Denominator Real & Imaginary Components... ***/ + + acc_den.real = 0.0; + acc_den.imag = 0.0; + + for (i=0; i 0.0 ) { /* Negative coefficient */ + /* values for this iteration. */ + if (frac > 0.0 ) { /** Odd Powers of "s" **/ + acc_den.imag = acc_den.imag - *(den_coefficient[i]) * pow(RAD_FREQ,i); + } + else { /** Even Powers of "s" **/ + acc_den.real = acc_den.real - *(den_coefficient[i]) * pow(RAD_FREQ,i); + } + } + else { /* Positive coefficient values for this iteration */ + if (frac > 0.0 ) { /** Odd Powers of "s" **/ + acc_den.imag = acc_den.imag + *(den_coefficient[i]) * pow(RAD_FREQ,i); + } + else { /** Even Powers of "s" **/ + acc_den.real = acc_den.real + *(den_coefficient[i]) * pow(RAD_FREQ,i); + } + } + } + + /* divide numerator values by denominator values */ + + ac_gain = cm_complex_div(acc_num, acc_den); + + AC_GAIN(out,in) = ac_gain; + } + + /* free all allocated memory */ + free(integrator); + free(old_integrator); + free(den_coefficient); + free(old_den_coefficient); +} + + + + + + + diff --git a/src/xspice/icm/analog/s_xfer/ifspec.ifs b/src/xspice/icm/analog/s_xfer/ifspec.ifs new file mode 100644 index 000000000..d62503596 --- /dev/null +++ b/src/xspice/icm/analog/s_xfer/ifspec.ifs @@ -0,0 +1,93 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 27 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog s-domain transfer function (s_xfer) code model. + +===============================================================================*/ + +NAME_TABLE: + +Spice_Model_Name: s_xfer +C_Function_Name: cm_s_xfer +Description: "s-domain transfer function block" + + +PORT_TABLE: + + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + + +PARAMETER_TABLE: + + +Parameter_Name: in_offset gain +Description: "input offset" "gain" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + + +Parameter_Name: num_coeff den_coeff +Description: "numerator poly coef" "denominator poly coef" +Data_Type: real real +Default_Value: - - +Limits: - - +Vector: yes yes +Vector_Bounds: [1 -] [1 -] +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + + +Parameter_Name: int_ic +Description: "int stage init. cond" +Data_Type: real +Default_Value: 0.0 +Limits: - +Vector: yes +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + + +Parameter_Name: denormalized_freq +Description: "frequency (radians/second) at which to denormalize coefficients" +Data_Type: real +Default_Value: 1.0 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + diff --git a/src/xspice/icm/analog/s_xfer/s_xfer.h b/src/xspice/icm/analog/s_xfer/s_xfer.h new file mode 100644 index 000000000..ce433da76 --- /dev/null +++ b/src/xspice/icm/analog/s_xfer/s_xfer.h @@ -0,0 +1,24 @@ + + +/***************************************************/ +/****** Structures, etc. for int model. ******/ +/****** 11/6/90 JPM ******/ +/***************************************************/ + +/***** Value Definitions ******************************************/ + +#define INT1 1 +#define INT2 2 + + + +/***** Define Macros **************************************/ + + + +/***** Structure Definitions *************************************/ + + + +/***** Function Prototype Definitions ***************************************/ + diff --git a/src/xspice/icm/analog/sine/cfunc.mod b/src/xspice/icm/analog/sine/cfunc.mod new file mode 100644 index 000000000..6dbe7756f --- /dev/null +++ b/src/xspice/icm/analog/sine/cfunc.mod @@ -0,0 +1,257 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE sine/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 20 Mar 1991 Harry Li + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the sine (controlled sine-wave + oscillator) code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include "sin.h" +#include + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_sine() + +AUTHORS + + 20 Mar 1991 Harry Li + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the sine (controlled sinewave + oscillator) code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_SINE ROUTINE ===*/ + +void cm_sine(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + int i; /* generic loop counter index */ + int cntl_size; /* control array size */ + int freq_size; /* frequency array size */ + + double *x; /* pointer to the control array values */ + double *y; /* pointer to the frequency array values */ + double cntl_input; /* control input */ + double out; /* output value */ + double dout_din; /* partial derivative of output wrt control in */ + double output_low; /* output low value */ + double output_hi; /* output high value */ + double *phase; /* pointer to the instantaneous phase value */ + double *phase1; /* pointer to the previous value for the phase */ + double freq; /* frequency of the sine wave */ + double center; /* dc offset for the sine wave */ + double peak; /* peak voltage value for the wave */ + double radian; /* phase value in radians */ + + Mif_Complex_t ac_gain; + + + /**** Retrieve frequently used parameters... ****/ + + + cntl_size = PARAM_SIZE(cntl_array); + freq_size = PARAM_SIZE(freq_array); + output_low = PARAM(out_low); + output_hi = PARAM(out_high); + + if(cntl_size != freq_size){ + cm_message_send(array_error); + return; + } + + if(INIT == 1){ + + phase = cm_analog_alloc(INT1,sizeof(double)); + + } + if(ANALYSIS == MIF_DC){ + + OUTPUT(out) = (output_hi + output_low)/2; + PARTIAL(out,cntl_in) = 0; + phase = cm_analog_get_ptr(INT1,0); + *phase = 0; + + }else + + if(ANALYSIS == MIF_TRAN){ + + phase = cm_analog_get_ptr(INT1,0); + phase1 = cm_analog_get_ptr(INT1,1); + + /* Allocate storage for breakpoint domain & freq. range values */ + x = (double *) calloc(cntl_size, sizeof(double)); + if (x == '\0') { + cm_message_send(allocation_error); + return; + } + y = (double *) calloc(freq_size, sizeof(double)); + if (y == '\0') { + cm_message_send(allocation_error); + return; + } + + + /* Retrieve x and y values. */ + for (i=0; i= *(x+cntl_size-1)){ + dout_din = (*(y+cntl_size-1) - *(y+cntl_size-2)) / + (*(x+cntl_size-1) - *(x+cntl_size-2)); + freq = *(y+cntl_size-1) + (cntl_input - *(x+cntl_size-1)) * dout_din; + + } else { /*** cntl_input within bounds of end midpoints... + must determine position progressively & then + calculate required output. ***/ + + for (i=0; i= *(x+i))) { + + /* Interpolate to the correct frequency value */ + + freq = ((cntl_input - *(x+i))/(*(x+i+1) - *(x+i)))* + (*(y+i+1)-*(y+i)) + *(y+i); + } + + } + } +/* calculate the peak value of the wave, the center of the wave, the + instantaneous phase and the radian value of the phase */ + peak = (output_hi - output_low)/2; + center = (output_hi + output_low)/2; + *phase = *phase1 + freq*(TIME - T(1)); + radian = *phase * 2.0 * PI; + + OUTPUT(out) = peak*sin(radian) + center; + PARTIAL(out,cntl_in) = 0; + + } else { /* Output AC Gain */ + + ac_gain.real = 0.0; + ac_gain.imag= 0.0; + AC_GAIN(out,cntl_in) = ac_gain; + } +} + diff --git a/src/xspice/icm/analog/sine/ifspec.ifs b/src/xspice/icm/analog/sine/ifspec.ifs new file mode 100644 index 000000000..4809805c9 --- /dev/null +++ b/src/xspice/icm/analog/sine/ifspec.ifs @@ -0,0 +1,61 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 20 Mar 1991 Harry Li + + +SUMMARY + + This file contains the interface specification file for the + analog sine (controlled sinewave oscillator) code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_sine +Spice_Model_Name: sine +Description: "controlled sine wave oscillator" + + +PORT_TABLE: + +Port_Name: cntl_in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + +PARAMETER_TABLE: + +Parameter_Name: cntl_array freq_array +Description: "control in array" "frequency array" +Data_Type: real real +Default_Value: 0.0 1.0e3 +Limits: - [0 -] +Vector: yes yes +Vector_Bounds: [2 -] [2 -] +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: out_low out_high +Description: "output low value" "output high value" +Data_Type: real real +Default_Value: -1.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + diff --git a/src/xspice/icm/analog/sine/sin.h b/src/xspice/icm/analog/sine/sin.h new file mode 100644 index 000000000..423026c6c --- /dev/null +++ b/src/xspice/icm/analog/sine/sin.h @@ -0,0 +1,80 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE sine/sin.h + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 20 Mar 1991 Harry Li + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains additional header information for the + sine code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +REFERENCED FILES + + NONE + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + +#define PI 3.141592654; + +#define INT1 1 + +char *allocation_error = "\n**** Error ****\nSINE: Error allocating sine block storage \n"; +char *limit_error = "\n**** Error ****\nSINE: Smoothing domain value too large \n"; +char *sine_freq_clamp = "\n**** Warning ****\nSINE: Extrapolated frequency limited to 1e-16 Hz \n"; +char *array_error = "\n**** Error ****\nSINE: Size of control array different than frequency array \n"; + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + diff --git a/src/xspice/icm/analog/slew/cfunc.mod b/src/xspice/icm/analog/slew/cfunc.mod new file mode 100644 index 000000000..bd0a1e16b --- /dev/null +++ b/src/xspice/icm/analog/slew/cfunc.mod @@ -0,0 +1,301 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE slew/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 15 Apr 1991 Harry Li + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the slew (slew rate) code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include "slew.h" + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_slew() + +AUTHORS + + 15 Apr 1991 Harry Li + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the slew code model. + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_SLEW ROUTINE ===*/ + +/**************************************************************** +* * +* This model describes a single input, single output slew * +* rate limited block. The user may specify the positive * +* and negative slew rates. * +* * +* Note that the model makes no provision for output high and * +* low values. That is assumed to be handled by another model. * +* * +****************************************************************/ + +void cm_slew(ARGS) + +{ + double *ins; /* input value */ + double *in_old; /* previous input value */ + double *outs; /* output value */ + double *out_old; /* previous output value */ + double pout_pin; /* partial derivative--output wrt input */ + double delta; /* change in time from previous iteration */ + double slope_rise; /* positive going slew rate */ + double slope_fall; /* negative going slew rate */ + double out_slew; /* "slewed" output value */ + double slope; /* slope of the input wrt time */ + + Mif_Complex_t ac_gain; + + /** Retrieve frequently used parameters (used by all analyses)... **/ + + if (INIT == 1) { + + /* First pass...allocate storage for previous state. */ + + ins = cm_analog_alloc(INT1,sizeof(double)); + outs = cm_analog_alloc(INT4,sizeof(double)); + out_old = cm_analog_alloc(INT2,sizeof(double)); + in_old = cm_analog_alloc(INT3,sizeof(double)); + + } + + if (ANALYSIS == MIF_DC) { + + /* DC analysis, get old values */ + + ins= cm_analog_get_ptr(INT1,0); + outs= cm_analog_get_ptr(INT4,0); + in_old = cm_analog_get_ptr(INT1,0); + out_old = cm_analog_get_ptr(INT4,0); + + *ins = *in_old = INPUT(in); + *outs = *out_old = *ins; + + /*** so, return a zero d/dt value. ***/ + pout_pin = 1.0; + + OUTPUT(out) = INPUT(in); + PARTIAL(out,in) = 1; + + }else + + if (ANALYSIS == MIF_TRAN) { /**** DC & Transient Analyses ****/ + + /** Retrieve frequently used parameters... **/ + + slope_rise = PARAM(rise_slope); + slope_fall = PARAM(fall_slope); + + /* Allocation not necessary...retrieve previous values */ + + ins = cm_analog_get_ptr(INT1,0); /* Set out pointer to current + time storage */ + in_old = cm_analog_get_ptr(INT1,1); /* Set old-output-state pointer */ + outs = cm_analog_get_ptr(INT4,0); + out_old = cm_analog_get_ptr(INT4,1); /* Set old-output-state pointer + previous time storage */ + + + if ( TIME == 0.0 ) { /*** Test to see if this is the first ***/ + /*** timepoint calculation...if ***/ + + *ins = *in_old = INPUT(in); + *outs = *out_old = *ins; /* input = output, d/dt = 1 */ + pout_pin = 1.0; + + }else{ + + /* determine the slope of the input */ + delta = TIME - T(1); + *ins = INPUT(in); + slope = (*ins - *in_old)/delta; + + if(slope >= 0){ + + out_slew = *out_old + slope_rise*delta; + + if(*ins < (*out_old - slope_fall*delta)){ + + /* If the input had a negative slope (and the output + was slewing) and then changed direction to a positive + slope and the "slewed" response hasn't caught up + to the input yet (input < slewed output), then + continue negative slewing until the slewed output + meets the positive sloping input */ + + *outs = *out_old - slope_fall*delta; + pout_pin = 0; + + }else + + /* Two conditions for slewing, if the slope is greater + than the positive slew rate, or if the input slope + is less than the positive slew rate and the slewed output + is less than the input. This second condition occurs + if the input levels off and the slewed output hasn't + caught up to the input yet */ + + if((slope > slope_rise) || ((slope < slope_rise) && (out_slew <= *ins))){ + /* SLEWING ! */ + *outs = out_slew; + pout_pin = 0; + + }else{ + /* No slewing, output=input */ + *outs = *ins; + pout_pin = 1; + + } + + }else{ /* this ends the positive slope stuff */ + + out_slew = *out_old - slope_fall*delta; + + if(*ins > (*out_old + slope_rise*delta)){ + + /* If the input had a positive slope (and the output + was slewing) and then changed direction to a negative + slope and the "slewed" response hasn't caught up + to the input yet (input > slewed output), then + continue positive slewing until the slewed output + meets the negative sloping input */ + + *outs = *out_old + slope_rise*delta; + pout_pin = 0; + + }else + + /* Two conditions for slewing, if the negative slope is + greater than the neg. slew rate, or if the neg. input + slope is less than the negative slew rate and the + slewed output is greater than the input. This second + condition occurs if the input levels off and the + slewed output hasn't caught up to the input yet */ + + if((-slope > slope_fall) || ((-slope < slope_fall) && (out_slew > *ins))){ /* SLEWING ! */ + *outs = out_slew; + pout_pin = 0; + + }else{ + + *outs = *ins; + pout_pin = 1; + + } + + + } + + } + /** Output values for DC & Transient **/ + + OUTPUT(out) = *outs; + PARTIAL(out,in) = pout_pin; + + + }else{ /**** AC Analysis...output (0.0,s*gain) ****/ + ac_gain.real = 1.0; + ac_gain.imag= 0; + AC_GAIN(out,in) = ac_gain; + } +} + + + + + diff --git a/src/xspice/icm/analog/slew/ifspec.ifs b/src/xspice/icm/analog/slew/ifspec.ifs new file mode 100644 index 000000000..409559bed --- /dev/null +++ b/src/xspice/icm/analog/slew/ifspec.ifs @@ -0,0 +1,54 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 15 Apr 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog slew (slew rate) code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_slew +Spice_Model_Name: slew +Description: "a simple slew rate follower block" + + +PORT_TABLE: + + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + + +Parameter_Name: rise_slope fall_slope +Description: "rising slew limit" "falling slew limit" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + diff --git a/src/xspice/icm/analog/slew/slew.h b/src/xspice/icm/analog/slew/slew.h new file mode 100644 index 000000000..a881d7c04 --- /dev/null +++ b/src/xspice/icm/analog/slew/slew.h @@ -0,0 +1,77 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE slew/slew.h + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 15 Apr 1991 Harry Li + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains additional header information for the + slew code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +REFERENCED FILES + + NONE + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + +#define INT1 1 +#define INT2 2 +#define INT3 3 +#define INT4 4 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + diff --git a/src/xspice/icm/analog/square/cfunc.mod b/src/xspice/icm/analog/square/cfunc.mod new file mode 100644 index 000000000..bdff79c2d --- /dev/null +++ b/src/xspice/icm/analog/square/cfunc.mod @@ -0,0 +1,412 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE square/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 12 Apr 1991 Harry Li + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the square (controlled squarewave + oscillator) code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_set_temp_bkpt() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include "square.h" + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_square() + +AUTHORS + + 12 Apr 1991 Harry Li + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the square (controlled squarewave + oscillator) code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_set_temp_bkpt() + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_SQUARE ROUTINE ===*/ + + +/*********************************************************** +* * +* I <-dutycycle-> * +* I * +* I out_high * +* I t2 | t3 * +* I \____v_____/ * +* I / \ * +* I * +* I / \ * +* I * +* I / \ * +* I * +* I-----------------I I--------------- * +* ^ t1 t4 * +* | * +* out_low * +* t2 = t1 + t_rise * +* t4 = t3 + t_fall * +* * +***********************************************************/ + +void cm_square(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + int i; /* generic loop counter index */ + int cntl_size; /* control array size */ + int freq_size; /* frequency array size */ + int int_cycle; /* integer number of cycles */ + + double *x; /* pointer to the control array values */ + double *y; /* pointer to the frequecy array values */ + double cntl_input; /* control input */ + double out; /* output */ + double dout_din; /* slope of the frequency array wrt the control + array. Used to extrapolate a frequency above + and below the control input high and low level */ + double output_low; /* output low */ + double output_hi; /* output high */ + double dphase; /* fractional part into cycle */ + double *phase; /* pointer to the phase value */ + double *phase1; /* pointer to the old phase value */ + double freq; /* frequency of the wave */ + double d_cycle; /* duty cycle */ + double *t1; /* pointer containing the value of time1 */ + double *t2; /* pointer containing the value of time2 */ + double *t3; /* pointer containing the value of time3 */ + double *t4; /* pointer containing the value of time4 */ + double time1; /* time1 = duty_cycle * period of the wave */ + double time2; /* time2 = time1 + risetime */ + double time3; /* time3 = current time+time to end of period*/ + double time4; /* time4 = time3 + falltime */ + double t_rise; /* risetime */ + double t_fall; /* falltime */ + + Mif_Complex_t ac_gain; + + /**** Retrieve frequently used parameters... ****/ + + cntl_size = PARAM_SIZE(cntl_array); + freq_size = PARAM_SIZE(freq_array); + output_low = PARAM(out_low); + output_hi = PARAM(out_high); + d_cycle = PARAM(duty_cycle); + t_rise = PARAM(rise_time); + t_fall = PARAM(fall_time); + + /* check and make sure that the control array is the + same size as the frequency array */ + + if(cntl_size != freq_size){ + cm_message_send(square_array_error); + return; + } + + /* First time throught allocate memory */ + if(INIT==1){ + phase = cm_analog_alloc(INT1,sizeof(double)); + t1 = cm_analog_alloc(T1,sizeof(double)); + t2 = cm_analog_alloc(T2,sizeof(double)); + t3 = cm_analog_alloc(T3,sizeof(double)); + t4 = cm_analog_alloc(T4,sizeof(double)); + + } + + if(ANALYSIS == MIF_DC){ + + /* initialize time values */ + t1 = cm_analog_get_ptr(T1,0); + t2 = cm_analog_get_ptr(T2,0); + t3 = cm_analog_get_ptr(T3,0); + t4 = cm_analog_get_ptr(T4,0); + + *t1 = -1; + *t2 = -1; + *t3 = -1; + *t4 = -1; + + OUTPUT(out) = output_low; + PARTIAL(out,cntl_in) = 0; + + }else + + /* Retrieve previous values */ + + if(ANALYSIS == MIF_TRAN){ + + phase = cm_analog_get_ptr(INT1,0); + phase1 = cm_analog_get_ptr(INT1,1); + t1 = cm_analog_get_ptr(T1,1); + t2 = cm_analog_get_ptr(T2,1); + t3 = cm_analog_get_ptr(T3,1); + t4 = cm_analog_get_ptr(T4,1); + + time1 = *t1; + time2 = *t2; + time3 = *t3; + time4 = *t4; + + /* Allocate storage for breakpoint domain & freq. range values */ + + x = (double *) calloc(cntl_size, sizeof(double)); + if (x == '\0') { + cm_message_send(square_allocation_error); + return; + } + + y = (double *) calloc(freq_size, sizeof(double)); + if (y == '\0') { + cm_message_send(square_allocation_error); + return; + } + + /* Retrieve x and y values. */ + for (i=0; i= *(x+cntl_size-1)){ + dout_din = (*(y+cntl_size-1) - *(y+cntl_size-2)) / + (*(x+cntl_size-1) - *(x+cntl_size-2)); + freq = *(y+cntl_size-1) + (cntl_input - *(x+cntl_size-1)) * dout_din; + /* freq = *(y+cntl_size-1); */ + + } else { /*** cntl_input within bounds of end midpoints... + must determine position progressively & then + calculate required output. ***/ + + for (i=0; i= *(x+i))){ + + /* Interpolate to the correct frequency value */ + + freq = ((cntl_input - *(x+i))/(*(x+i+1) - *(x+i)))* + (*(y+i+1)-*(y+i)) + *(y+i); + } + + } + } + /* calculate the instantaneous phase */ + *phase = *phase1 + freq*(TIME - T(1)); + + /* convert the phase to an integer */ + int_cycle = *phase1; + + /* dphase is the percent into the cycle for + the period */ + dphase = *phase1 - int_cycle; + + /* Calculate the time variables and the output value + for this iteration */ + + if((time1 <= TIME) && (TIME <= time2)){ + time3 = T(1) + (1 - dphase)/freq; + time4 = time3 + t_fall; + + if(TIME < time2){ + cm_analog_set_temp_bkpt(time2); + } + + cm_analog_set_temp_bkpt(time3); + cm_analog_set_temp_bkpt(time4); + + OUTPUT(out) = output_low + ((TIME - time1)/(time2 - time1))* + (output_hi - output_low); + + }else + + if((time2 <= TIME) && (TIME <= time3)){ + + time3 = T(1) + (1.0 - dphase)/freq; + time4 = time3 + t_fall; + if(TIME < time3){ + cm_analog_set_temp_bkpt(time3); + } + cm_analog_set_temp_bkpt(time4); + OUTPUT(out) = output_hi; + + }else + + if((time3 <= TIME) && (TIME <= time4)){ + + if(dphase > 1-d_cycle){ + dphase = dphase - 1.0; + } + + /* subtract d_cycle from 1 because my initial definition + of duty cyle was that part of the cycle which the output + is low. The more standard definition is the part of the + cycle where the output is high. */ + time1 = T(1) + ((1-d_cycle) - dphase)/freq; + time2 = time1 + t_rise; + + if(TIME < time4){ + cm_analog_set_temp_bkpt(time4); + } + + cm_analog_set_temp_bkpt(time1); + cm_analog_set_temp_bkpt(time2); + + OUTPUT(out) = output_hi + ((TIME - time3)/(time4 - time3))* + (output_low - output_hi); + + }else{ + + if(dphase > 1-d_cycle){ + dphase = dphase - 1.0; + } + + /* subtract d_cycle from 1 because my initial definition + of duty cyle was that part of the cycle which the output + is low. The more standard definition is the part of the + cycle where the output is high. */ + time1 = T(1) + ((1-d_cycle) - dphase)/freq; + time2 = time1 + t_rise; + + if((TIME < time1) || (T(1) == 0)){ + cm_analog_set_temp_bkpt(time1); + } + + cm_analog_set_temp_bkpt(time2); + OUTPUT(out) = output_low; + } + + PARTIAL(out,cntl_in) = 0.0; + + /* set the time values for storage */ + + t1 = cm_analog_get_ptr(T1,0); + t2 = cm_analog_get_ptr(T2,0); + t3 = cm_analog_get_ptr(T3,0); + t4 = cm_analog_get_ptr(T4,0); + + *t1 = time1; + *t2 = time2; + *t3 = time3; + *t4 = time4; + + } else { /* Output AC Gain */ + + /* This model has no AC capabilities */ + + ac_gain.real = 0.0; + ac_gain.imag= 0.0; + AC_GAIN(out,cntl_in) = ac_gain; + } +} + diff --git a/src/xspice/icm/analog/square/ifspec.ifs b/src/xspice/icm/analog/square/ifspec.ifs new file mode 100644 index 000000000..f3c2face2 --- /dev/null +++ b/src/xspice/icm/analog/square/ifspec.ifs @@ -0,0 +1,83 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 12 Apr 1991 Harry Li + + +SUMMARY + + This file contains the interface specification file for the + analog square (controlled squarewave oscillator) code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_square +Spice_Model_Name: square +Description: "controlled square wave oscillator" + + +PORT_TABLE: + +Port_Name: cntl_in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + +PARAMETER_TABLE: + +Parameter_Name: cntl_array freq_array +Description: "control in array" "frequency array" +Data_Type: real real +Default_Value: 0.0 1.0e3 +Limits: - [0 -] +Vector: yes yes +Vector_Bounds: [2 -] [2 -] +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: out_low out_high +Description: "output low value" "output high value" +Data_Type: real real +Default_Value: -1.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: duty_cycle rise_time +Description: "duty cycle" "rise time" +Data_Type: real real +Default_Value: 0.5 1.0e-9 +Limits: [1e-6 .999999] - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: fall_time +Description: "fall time" +Data_Type: real +Default_Value: 1.0e-9 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + diff --git a/src/xspice/icm/analog/square/square.h b/src/xspice/icm/analog/square/square.h new file mode 100644 index 000000000..773164c75 --- /dev/null +++ b/src/xspice/icm/analog/square/square.h @@ -0,0 +1,84 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE square/square.h + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 12 Apr 1991 Harry Li + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains additional header information for the + square (controlled squarewave oscillator) code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +REFERENCED FILES + + NONE + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + +char *square_allocation_error = "\n**** Error ****\nSQUARE: Error allocating square block storage \n"; +char *square_limit_error = "\n**** Error ****\nSQUARE: Smoothing domain value too large \n"; +char *square_freq_clamp = "\n**** WARNING ****\nSQUARE: Frequency extrapolation limited to 1e-16 \n"; +char *square_array_error = "\n**** Error ****\nSQUARE: Size of control array different than frequency array \n"; + + +#define INT1 1 +#define T1 2 +#define T2 3 +#define T3 4 +#define T4 5 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + diff --git a/src/xspice/icm/analog/summer/cfunc.mod b/src/xspice/icm/analog/summer/cfunc.mod new file mode 100644 index 000000000..c3c87d5e9 --- /dev/null +++ b/src/xspice/icm/analog/summer/cfunc.mod @@ -0,0 +1,150 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE summer/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 9 Apr 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the summer code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_summer() + +AUTHORS + + 9 Apr 1991 Jeffrey P. Murray + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the summer code model. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_SUMMER ROUTINE ===*/ + + +void cm_summer(ARGS) + +{ + int i; /* generic loop counter index */ + int size; /* number of inputs */ + + double accumulate; /* sum of all the (inputs times their + respective gains plus their offset). */ + double final_gain; /* output gain stage */ + double in_gain_temp; /* temporary variable used to calculate + accumulate */ + + Mif_Complex_t ac_gain; + + + size = PORT_SIZE(in); /* Note that port size */ + final_gain = PARAM(out_gain); /* and out_gain are read only */ + /* once...saves access time. */ + if(ANALYSIS != MIF_AC) { /* DC & Transient */ + accumulate = 0.0; + for (i=0; i= *(x+cntl_size-1)){ + dout_din = (*(y+cntl_size-1) - *(y+cntl_size-2)) / + (*(x+cntl_size-1) - *(x+cntl_size-2)); + freq = *(y+cntl_size-1) + (cntl_input - *(x+cntl_size-1)) * dout_din; + /* freq = *(y+cntl_size-1); */ + + } else { /*** cntl_input within bounds of end midpoints... + must determine position progressively & then + calculate required output. ***/ + + for (i=0; i= *(x+i))){ + + /* Interpolate to the correct frequency value */ + + freq = ((cntl_input - *(x+i))/(*(x+i+1) - *(x+i)))* + (*(y+i+1)-*(y+i)) + *(y+i); + } + + } + } + +/* Instantaneous phase is the old phase + frequency/(delta time) + int_cycle is the integer value for the number cycles. */ + + *phase = *phase1 + freq*(TIME - T(1)); + int_cycle = *phase1; + dphase = *phase1 - int_cycle; + /* if the current time is greater than time1, but less than time2, + calculate time2 and set the temporary breakpoint. */ + if((time1 <= TIME) && (TIME <= time2)){ + + time2 = T(1) + (1 - dphase)/freq; + + if(TIME < time2){ + cm_analog_set_temp_bkpt(time2); + } + + /* store the time that the next cycle is scheduled to begin */ + t_start = time2; + + /* set output value */ + OUTPUT(out) = output_hi - ((TIME - time1)/(time2 - time1))* + (output_hi - output_low); + + + }else{ + + /* otherwise, calculate time1 and time2 and set their respective + breakpoints */ + + if(dphase > d_cycle){ + dphase = dphase - 1.0; + } + + time1 = T(1) + (d_cycle - dphase)/freq; + time2 = T(1) + (1 - dphase)/freq; + + if((TIME < time1) || (T(1) == 0)){ + cm_analog_set_temp_bkpt(time1); + } + + cm_analog_set_temp_bkpt(time2); + + /* set output value */ + OUTPUT(out) = output_low + ((TIME - t_start)/(time1 - t_start))* + (output_hi - output_low); + } + + PARTIAL(out,cntl_in) = 0.0; + + /* set the time values for storage */ + + t1 = cm_analog_get_ptr(T1,0); + t2 = cm_analog_get_ptr(T2,0); + t_end = cm_analog_get_ptr(T3,0); + + *t1 = time1; + *t2 = time2; + *t_end = t_start; + + } else { /* Output AC Gain */ + + /* This model has no AC capabilities */ + + ac_gain.real = 0.0; + ac_gain.imag= 0.0; + AC_GAIN(out,cntl_in) = ac_gain; + } +} + diff --git a/src/xspice/icm/analog/triangle/ifspec.ifs b/src/xspice/icm/analog/triangle/ifspec.ifs new file mode 100644 index 000000000..24d69e6a6 --- /dev/null +++ b/src/xspice/icm/analog/triangle/ifspec.ifs @@ -0,0 +1,72 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 12 Apr 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog triangle (controlled trianglewave oscillator) code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_triangle +Spice_Model_Name: triangle +Description: "controlled triangle wave oscillator" + + +PORT_TABLE: + +Port_Name: cntl_in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + +PARAMETER_TABLE: + +Parameter_Name: cntl_array freq_array +Description: "control in array" "frequency array" +Data_Type: real real +Default_Value: 0.0 1.0e3 +Limits: - [0 -] +Vector: yes yes +Vector_Bounds: [2 -] [2 -] +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: out_low out_high +Description: "output low value" "output high value" +Data_Type: real real +Default_Value: -1.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + +PARAMETER_TABLE: + +Parameter_Name: duty_cycle +Description: "rise time duty cycle" +Data_Type: real +Default_Value: 0.5 +Limits: [1e-6 .999999] +Vector: no +Vector_Bounds: - +Null_Allowed: yes + diff --git a/src/xspice/icm/analog/triangle/triangle.h b/src/xspice/icm/analog/triangle/triangle.h new file mode 100644 index 000000000..0fecef7d5 --- /dev/null +++ b/src/xspice/icm/analog/triangle/triangle.h @@ -0,0 +1,81 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE triangle/triangle.h + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 12 Apr 1991 Harry Li + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains additional header information for the + triangle (controlled trianglewave oscillator) code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +REFERENCED FILES + + NONE + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + +char *triangle_allocation_error = "\n**** Error ****\nTRIANGLE: Error allocating triangle block storage \n"; +char *triangle_freq_clamp = "\n**** Warning ****\nTRIANGLE: Extrapolated Minimum Frequency Set to 1e-16 Hz \n"; +char *triangle_array_error = "\n**** Error ****\nTRIANGLE: Size of control array different than frequency array \n"; + + +#define INT1 1 +#define T1 2 +#define T2 3 +#define T3 4 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + diff --git a/src/xspice/icm/analog/udnpath.lst b/src/xspice/icm/analog/udnpath.lst new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/src/xspice/icm/analog/udnpath.lst @@ -0,0 +1,2 @@ + + diff --git a/src/xspice/icm/digital/adc_bridge/cfunc.mod b/src/xspice/icm/digital/adc_bridge/cfunc.mod new file mode 100644 index 000000000..a46cb1267 --- /dev/null +++ b/src/xspice/icm/digital/adc_bridge/cfunc.mod @@ -0,0 +1,355 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE adc_bridge/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 June 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 26 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the adc_bridge + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + int cm_event_queue() + + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + + +/*============================================================================== + +FUNCTION cm_adc_bridge() + +AUTHORS + + 6 June 1991 Jeffrey P. Murray + +MODIFICATIONS + + 26 Sept 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the adc_bridge code model. + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + int cm_event_queue() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_ADC_BRIDGE ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* analog-to-digital nodebridge for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/6/91 * +* Last Modified 7/26/91 J.P.Murray * +************************************************/ + + +void cm_adc_bridge(ARGS) + +{ + double in_low, /* analog output value corresponding to '0' + digital input */ + in_high, /* analog output value corresponding to '1' + digital input */ + current_time, /* the current time value */ + *in, /* base address of array holding all digital output + values plus their previous values */ + *in_old; /* base address of array holding previous + output values */ + + + int i, /* generic loop counter index */ + size; /* number of input & output ports */ + + + + Digital_State_t *out, /* base address of array holding all input + values plus their previous values */ + *out_old, /* base address of array holding previous + input values */ + test; /* temp holding variable for digital states */ + + + + + + /* determine "width" of the node bridge... */ + + size = PORT_SIZE(in); + in_high = PARAM(in_high); + in_low = PARAM(in_low); + + + + + if (INIT) { /*** Test for INIT == TRUE. If so, allocate storage, etc. ***/ + + + /* Allocate storage for inputs */ + + in = in_old = cm_analog_alloc(0,size * sizeof(double)); + + + /* Allocate storage for outputs */ + out = out_old = (Digital_State_t *) cm_event_alloc(1,size * sizeof(Digital_State_t)); + + } + + else { /*** This is not an initialization pass...retrieve storage + addresses and calculate new outputs, if required. ***/ + + + /** Retrieve previous values... **/ + + /* assign discrete addresses */ + in = cm_analog_get_ptr(0,0); + in_old = cm_analog_get_ptr(0,1); + + /* assign analog addresses */ + out = (Digital_State_t *) cm_event_get_ptr(1,0); + out_old = (Digital_State_t *) cm_event_get_ptr(1,1); + + } + + + /* read current input values */ + for (i=0; i= in_high) { /* high output required */ + + test = ONE; + + if ( test != out_old[i] ) { + /* call for event breakpoint... */ + current_time = TIME; + cm_event_queue(current_time); + } + else { + /* no change since last time */ + } + + } + else { /* unknown output required */ + + if ( UNKNOWN != out_old[i] ) { + + /* call for event breakpoint... */ + current_time = TIME; + cm_event_queue(current_time); + } + else { + /* no change since last time */ + } + } + } + } + + break; + + + + case EVENT: /** discrete call...lots to do **/ + + /* loop through all inputs... */ + for (i=0; i= in_high) { /* high output required */ + + out[i] = ONE; + + if ( out[i] != out_old[i] ) { + /* post changed value */ + OUTPUT_STATE(out[i]) = ONE; + OUTPUT_DELAY(out[i]) = PARAM(rise_delay); + } + else { + /* no change since last time */ + OUTPUT_CHANGED(out[i]) = FALSE; + } + + } + else { /* unknown output required */ + + out[i] = UNKNOWN; + + if ( UNKNOWN != out_old[i] ) { + + /* post changed value */ + OUTPUT_STATE(out[i]) = UNKNOWN; + + switch (out_old[i]) { + case ONE: + OUTPUT_DELAY(out[i]) = PARAM(fall_delay); + break; + + case ZERO: + OUTPUT_DELAY(out[i]) = PARAM(rise_delay); + break; + } + } + else { + /* no change since last time */ + OUTPUT_CHANGED(out[i]) = FALSE; + } + } + } + /* regardless, output the strength */ + OUTPUT_STRENGTH(out[i]) = STRONG; + } + break; + } + } + else { /*** TIME == 0.0 => set outputs to input value... ***/ + /* loop through all inputs... */ + for (i=0; i= in_high) { /* high output required */ + OUTPUT_STATE(out[i]) = out[i] = ONE; + } + else { + OUTPUT_STATE(out[i]) = out[i] = UNKNOWN; + } + OUTPUT_STRENGTH(out[i]) = STRONG; + } + } +} + + + diff --git a/src/xspice/icm/digital/adc_bridge/ifspec.ifs b/src/xspice/icm/digital/adc_bridge/ifspec.ifs new file mode 100644 index 000000000..200b6e108 --- /dev/null +++ b/src/xspice/icm/digital/adc_bridge/ifspec.ifs @@ -0,0 +1,73 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 26 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + hybrid adc_bridge code model. + +===============================================================================*/ + +NAME_TABLE: + +Spice_Model_Name: adc_bridge +C_Function_Name: cm_adc_bridge +Description: "analog-to-digital converter node bridge" + + +PORT_TABLE: + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v d +Allowed_Types: [v,vd,i,id,vnam] [d] +Vector: yes yes +Vector_Bounds: - - +Null_Allowed: no no + + + +PARAMETER_TABLE: + +Parameter_Name: in_low +Description: "maximum 0-valued analog input" +Data_Type: real +Default_Value: 0.1 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: in_high +Description: "minimum 1-valued analog input" +Data_Type: real +Default_Value: 0.9 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "rise delay" "fall delay" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes diff --git a/src/xspice/icm/digital/d_and/cfunc.mod b/src/xspice/icm/digital/d_and/cfunc.mod new file mode 100644 index 000000000..7c8b99534 --- /dev/null +++ b/src/xspice/icm/digital/d_and/cfunc.mod @@ -0,0 +1,247 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_and/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 14 June 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 27 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the d_and + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include +#include +#include +#include + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_d_and() + +AUTHORS + + 14 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 27 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_and code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_AND ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital AND gate for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/14/91 J.P.Murray * +************************************************/ + + +void cm_d_and(ARGS) + +{ + int i, /* generic loop counter index */ + size; /* number of input & output ports */ + + + + Digital_State_t *out, /* temporary output for buffers */ + *out_old, /* previous output for buffers */ + input; /* temp storage for input bits */ + + + /** Retrieve size value... **/ + size = PORT_SIZE(in); + + + + /*** Setup required state variables ***/ + + if(INIT) { /* initial pass */ + + /* allocate storage for the outputs */ + out = out_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + + /* set loading for inputs */ + for (i=0; i +#include +#include +#include + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_d_fdiv() + +AUTHORS + + 10 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 22 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_fdiv code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_FDIV ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital frequency divider for the * +* ATESSE Version 2.0 system. * +* * +* Created 7/10/91 J.P.Murray * +************************************************/ + + +void cm_d_fdiv(ARGS) + +{ + int div_factor; /* division factor */ + + + Digital_State_t *freq_in, /* freq_in clock value */ + *freq_in_old, /* previous freq_in value */ + *freq_out, /* current output for fdiv */ + *freq_out_old, /* previous output for fdiv */ + + *count, /* counter value */ + *count_old; /* previous counter value */ + + + + /*** Setup required state variables ***/ + + if(INIT) { /* initial pass */ + + /* allocate storage */ + freq_in = freq_in_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + freq_out = freq_out_old = (Digital_State_t *) cm_event_alloc(1,sizeof(Digital_State_t)); + count = count_old = (Digital_State_t *) cm_event_alloc(2,sizeof(Digital_State_t)); + + /* declare load values */ + LOAD(freq_in) = PARAM(freq_in_load); + + } + else { /* Retrieve previous values */ + + /* retrieve storage for the outputs */ + freq_in = (Digital_State_t *) cm_event_get_ptr(0,0); + freq_in_old = (Digital_State_t *) cm_event_get_ptr(0,1); + freq_out = (Digital_State_t *) cm_event_get_ptr(1,0); + freq_out_old = (Digital_State_t *) cm_event_get_ptr(1,1); + count = (Digital_State_t *) cm_event_get_ptr(2,0); + count_old = (Digital_State_t *) cm_event_get_ptr(2,1); + + } + + + + /*** Output the strength of freq_out (always strong)... ***/ + OUTPUT_STRENGTH(freq_out) = STRONG; + + + /** Retrieve parameters */ + div_factor = PARAM(div_factor); + + + /******* Determine analysis type and output appropriate values *******/ + + if (0.0 == TIME) { /****** DC analysis...output w/o delays ******/ + + + /* read initial count value, normalize, and if it is out of + bounds, set to "zero" equivalent */ + *count = PARAM(i_count); + if ( (div_factor <= *count) || (0 > *count) ) { + *count = 0; + OUTPUT_STATE(freq_out) = *freq_out = *freq_out_old = ZERO; + } + + if ( (0 < *count) && (*count <= PARAM(high_cycles)) ) { + OUTPUT_STATE(freq_out) = *freq_out = *freq_out_old = ONE; + } + + } + + else { /****** Transient Analysis ******/ + + /*** load current input value... ***/ + *freq_in = INPUT_STATE(freq_in); + + + /**** Test to see if the input has provided an edge... ****/ + if ( (*freq_in != *freq_in_old)&&(*freq_in == 1) ) { + + /** An edge has been provided...revise count value **/ + *count = *count_old + 1; + + /* If new count value is equal to the div_factor+1 value, + need to normalize count to "1", and raise output */ + if ( ((div_factor+1) == *count)||(1 == *count) ) { + *count = 1; + OUTPUT_STATE(freq_out) = *freq_out = ONE; + OUTPUT_DELAY(freq_out) = PARAM(rise_delay); + } + else { + /* If new count value is equal to the + high_cycles+1 value, drop the output to ZERO */ + if ( ( PARAM(high_cycles)+1) == *count ) { + OUTPUT_STATE(freq_out) = *freq_out = ZERO; + OUTPUT_DELAY(freq_out) = PARAM(fall_delay); + } + else { + OUTPUT_CHANGED(freq_out) = FALSE; + } + } + } + else { /** Output does not change!! **/ + + OUTPUT_CHANGED(freq_out) = FALSE; + + } + } +} + + + + + diff --git a/src/xspice/icm/digital/d_fdiv/ifspec.ifs b/src/xspice/icm/digital/d_fdiv/ifspec.ifs new file mode 100644 index 000000000..963377a42 --- /dev/null +++ b/src/xspice/icm/digital/d_fdiv/ifspec.ifs @@ -0,0 +1,86 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_fdiv (frequency divider) code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_d_fdiv +Spice_Model_Name: d_fdiv +Description: "digital frequency divider" + + +PORT_TABLE: + +Port_Name: freq_in freq_out +Description: "frequency input" "frequency output" +Direction: in out +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: div_factor high_cycles +Description: "divide factor" "number of high clock cycles" +Data_Type: int int +Default_Value: 2 1 +Limits: [1 -] [1 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: i_count +Description: "output initial count value" +Data_Type: int +Default_Value: 0 +Limits: [0 -] +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "rise delay" "fall delay" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: freq_in_load +Description: "freq_in load value (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + diff --git a/src/xspice/icm/digital/d_inverter/cfunc.mod b/src/xspice/icm/digital/d_inverter/cfunc.mod new file mode 100644 index 000000000..4e808ee83 --- /dev/null +++ b/src/xspice/icm/digital/d_inverter/cfunc.mod @@ -0,0 +1,211 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_inverter/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 14 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include +#include +#include +#include + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_d_inverter() + +AUTHORS + + 14 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_inverter code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_INVERTER ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital inverter gate for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/14/91 J.P.Murray * +************************************************/ + + +void cm_d_inverter(ARGS) + +{ + int i; /* generic loop counter index */ + + + + Digital_State_t *out, /* temporary output for inverter */ + *out_old; /* previous output for inverter */ + + + /** Setup required state variables **/ + + if(INIT) { /* initial pass */ + + /* allocate storage for the outputs */ + out = out_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + + /* define load value on inputs */ + LOAD(in) = PARAM(input_load); + + } + else { /* Retrieve previous values */ + + /* retrieve storage for the outputs */ + out = (Digital_State_t *) cm_event_get_ptr(0,0); + out_old = (Digital_State_t *) cm_event_get_ptr(0,1); + } + + + /** Check on analysis type **/ + + if (ANALYSIS == DC) { /* DC analysis...output w/o delays */ + + switch ( INPUT_STATE(in) ) { + + case ZERO: + OUTPUT_STATE(out) = *out = *out_old = ONE; + break; + + case ONE: + OUTPUT_STATE(out) = *out = *out_old = ZERO; + break; + + default: + OUTPUT_STATE(out) = *out = *out_old = UNKNOWN; + break; + } + + } + else { /* Transient Analysis */ + + switch ( INPUT_STATE(in) ) { + + /* fall to zero value */ + case 1: OUTPUT_STATE(out) = *out = 0; + OUTPUT_DELAY(out) = PARAM(fall_delay); + break; + + /* rise to one value */ + case 0: OUTPUT_STATE(out) = *out = 1; + OUTPUT_DELAY(out) = PARAM(rise_delay); + break; + + /* unknown output */ + default: + OUTPUT_STATE(out) = *out = UNKNOWN; + + /* based on old value, add rise or fall delay */ + if (0 == *out_old) { /* add rising delay */ + OUTPUT_DELAY(out) = PARAM(rise_delay); + } + else { /* add falling delay */ + OUTPUT_DELAY(out) = PARAM(fall_delay); + } + break; + } + } + + OUTPUT_STRENGTH(out) = STRONG; +} + + + + diff --git a/src/xspice/icm/digital/d_inverter/ifspec.ifs b/src/xspice/icm/digital/d_inverter/ifspec.ifs new file mode 100644 index 000000000..c09d4ec8b --- /dev/null +++ b/src/xspice/icm/digital/d_inverter/ifspec.ifs @@ -0,0 +1,62 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_inverter code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_d_inverter +Spice_Model_Name: d_inverter +Description: "digital one-bit-wide inverter" + + +PORT_TABLE: + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "rise delay" "fall delay" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: input_load +Description: "input load value (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + diff --git a/src/xspice/icm/digital/d_jkff/cfunc.mod b/src/xspice/icm/digital/d_jkff/cfunc.mod new file mode 100644 index 000000000..5e05948ef --- /dev/null +++ b/src/xspice/icm/digital/d_jkff/cfunc.mod @@ -0,0 +1,765 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_jkff/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 21 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 12 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + 29 Jan 1992 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the d_jkff + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_toggle_bit() + + +AUTHORS + + 27 Sept 1991 Jeffrey P. Murray + + +MODIFICATIONS + + NONE + + +SUMMARY + + Alters the state of a passed digital variable to its + complement. Thus, a ONE changes to a ZERO. A ZERO changes + to a ONE, and an UNKNOWN remains unchanged. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + No returned value. Passed pointer to variable is used + to redefine the variable value. + + +GLOBAL VARIABLES + + NONE + + +NON-STANDARD FEATURES + + NONE + + +===============================================================================*/ + +/*=== CM_TOGGLE_BIT ROUTINE ===*/ + +static void cm_toggle_bit(Digital_State_t *bit) + +{ + /* Toggle bit from ONE to ZERO or vice versa, unless the + bit value is UNKNOWN. In the latter case, return + without changing the bit value. */ + + if ( UNKNOWN != *bit ) { + if ( ONE == *bit ) { + *bit = ZERO; + } + else { + *bit = ONE; + } + } + +} + +/*============================================================================== + +FUNCTION cm_eval_jk_result + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + Evaluates the J and K input states, plus the last state of + the flip flop, and returns the expected output value. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + +RETURNED VALUE + + A Digital_State_t. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_EVAL_JK_RESULT ROUTINE ===*/ + +static Digital_State_t cm_eval_jk_result(Digital_State_t j_input, + Digital_State_t k_input, + Digital_State_t old_output) +{ + Digital_State_t output; /* returned output value */ + + + switch (j_input) { + + case ZERO: + switch (k_input) { + case ZERO: + output = old_output; + break; + case ONE: + output = ZERO; + break; + case UNKNOWN: + output = UNKNOWN; + break; + } + break; + + case ONE: + switch (k_input) { + case ZERO: + output = ONE; + break; + case ONE: + output = old_output; + cm_toggle_bit(&output); + break; + case UNKNOWN: + output = UNKNOWN; + break; + } + break; + + + case UNKNOWN: + output = UNKNOWN; + break; + } + + return output; + +} + +/*============================================================================== + +FUNCTION cm_d_jkff() + +AUTHORS + + 21 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 12 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + 29 Jan 1992 Jeffrey P. Murray + +SUMMARY + + This function implements the d_jkff code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + + +/*=== CM_D_JKFF ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital jk-type flip flop for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/21/91 J.P.Murray * +************************************************/ + + +void cm_d_jkff(ARGS) + +{ + int i; /* generic loop counter index */ + + + Digital_State_t *clk, /* current clk value */ + *clk_old, /* previous clk value */ + *set, /* current set value for dff */ + *set_old, /* previous set value for dff */ + *reset, /* current reset value for dff */ + *reset_old, /* previous reset value for dff */ + *out, /* current output for dff */ + *out_old, /* previous output for dff */ + + j_input, /* current j input value */ + k_input, /* current k input value */ + + temp; /* temp storage for state values */ + + + + /*** Setup required state variables ***/ + + if(INIT) { /* initial pass */ + + /* allocate storage */ + clk = clk_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + set = set_old = (Digital_State_t *) cm_event_alloc(1,sizeof(Digital_State_t)); + reset = reset_old = (Digital_State_t *) cm_event_alloc(2,sizeof(Digital_State_t)); + out = out_old = (Digital_State_t *) cm_event_alloc(3,sizeof(Digital_State_t)); + + /* declare load values */ + LOAD(j) = PARAM(jk_load); + LOAD(k) = PARAM(jk_load); + LOAD(clk) = PARAM(clk_load); + if ( !PORT_NULL(set) ) { + LOAD(set) = PARAM(set_load); + } + if ( !PORT_NULL(reset) ) { + LOAD(reset) = PARAM(reset_load); + } + + } + else { /* Retrieve previous values */ + + /* retrieve storage for the outputs */ + clk = (Digital_State_t *) cm_event_get_ptr(0,0); + clk_old = (Digital_State_t *) cm_event_get_ptr(0,1); + set = (Digital_State_t *) cm_event_get_ptr(1,0); + set_old = (Digital_State_t *) cm_event_get_ptr(1,1); + reset = (Digital_State_t *) cm_event_get_ptr(2,0); + reset_old = (Digital_State_t *) cm_event_get_ptr(2,1); + out = (Digital_State_t *) cm_event_get_ptr(3,0); + out_old = (Digital_State_t *) cm_event_get_ptr(3,1); + } + + + + /******** load current input values if set or reset + are not connected, set to zero... ********/ + *clk = INPUT_STATE(clk); + if ( PORT_NULL(set) ) { + *set = *set_old = ZERO; + } + else { + *set = INPUT_STATE(set); + } + if ( PORT_NULL(reset) ) { + *reset = *reset_old = ZERO; + } + else { + *reset = INPUT_STATE(reset); + } + + + + + + /******* Determine analysis type and output appropriate values *******/ + + if (0.0 == TIME) { /****** DC analysis...output w/o delays ******/ + + temp = PARAM(ic); + + /** Modify output if set or reset lines are active **/ + if ( (*set==ONE) && (*reset==ZERO) ) temp = ONE; + if ( (*set==ZERO) && (*reset==ONE) ) temp = ZERO; + if ( (*set==ONE) && (*reset==ONE) ) temp = UNKNOWN; + + *out = *out_old = temp; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + } + + cm_toggle_bit(&temp); + + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = temp; + } + + } + + else { /****** Transient Analysis ******/ + + + /***** Find input that has changed... *****/ + + /**** Test set value for change ****/ + if ( *set != *set_old ) { /* either set or set release */ + switch ( *set ) { + + case ONE: + if ( ONE != *reset) { + if (*out_old != ONE) { /* set will change output */ + /* output goes to ONE */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already set */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != UNKNOWN) { /* set will change output */ + /* output goes to UNKNOWN */ + *out = UNKNOWN; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = UNKNOWN; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = UNKNOWN; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case ZERO: + if ( ONE != *reset) { + /* output remains at current value */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + else { + if (*out_old != ZERO) { /* set will change output */ + /* output returns to reset condition */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case UNKNOWN: + + if ( ONE == *reset ) { + /* output goes to ZERO */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + } + } + else { + + /**** Test reset value for change ****/ + if ( *reset != *reset_old ) { /* either reset or reset release */ + switch ( *reset ) { + + case ONE: + if ( ONE != *set) { + if (*out_old != ZERO) { /* reset will change output */ + /* output goes to ZERO */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != UNKNOWN) { /* reset will change output */ + /* output goes to UNKNOWN */ + *out = UNKNOWN; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = UNKNOWN; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = UNKNOWN; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case ZERO: + if ( ONE != *set) { + /* output remains at current value */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + else { + if (*out_old != ONE) { /* reset will change output */ + /* output returns to set condition */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case UNKNOWN: + if ( ONE == *set ) { + /* output goes to ONE */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + } + } + else { + + /**** Test clk value for change ****/ + if ( (*clk != *clk_old) && (*reset != ONE) && + (*set != ONE) ) { /* clock or clock release */ + switch ( *clk ) { + + case ONE: + /* active edge...calculate new data output */ + j_input = INPUT_STATE(j); + k_input = INPUT_STATE(k); + temp = cm_eval_jk_result(j_input,k_input,*out_old); + + + if (*out_old != temp) { /* clk will change output */ + *out = temp; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + OUTPUT_DELAY(out) = PARAM(clk_delay); + } + cm_toggle_bit(&temp); + + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = temp; + OUTPUT_DELAY(Nout) = PARAM(clk_delay); + } + } + else { + *out = *out_old; /* output same as before */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + + case ZERO: + case UNKNOWN: + /* inactive edge...return previous values */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + break; + } + } + + else { /* data value must have changed... + return previous output value. */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + } + + + /***** Add additional rise or fall delays, if appropriate *****/ + + if ( *out != *out_old ) { /*** output value is changing ***/ + + switch ( *out ) { + + /** fall to zero value **/ + case 0: + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(fall_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(rise_delay); + } + break; + + /** rise to one value **/ + case 1: + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(rise_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(fall_delay); + } + break; + + /** unknown output **/ + default: + /* based on old value, add rise or fall delay */ + if (0 == *out_old) { /* add rising delay */ + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(rise_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(fall_delay); + } + } + else { /* add falling delay */ + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(fall_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(rise_delay); + } + } + break; + } + } + } + + /*** output strength values ***/ + if ( !PORT_NULL(out) ) { + OUTPUT_STRENGTH(out) = STRONG; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STRENGTH(Nout) = STRONG; + } +} + + + + + diff --git a/src/xspice/icm/digital/d_jkff/ifspec.ifs b/src/xspice/icm/digital/d_jkff/ifspec.ifs new file mode 100644 index 000000000..131d5f269 --- /dev/null +++ b/src/xspice/icm/digital/d_jkff/ifspec.ifs @@ -0,0 +1,135 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_jkff code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_d_jkff +Spice_Model_Name: d_jkff +Description: "digital jk-type flip flop" + + +PORT_TABLE: + +Port_Name: j k +Description: "j input" "k input" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PORT_TABLE: + +Port_Name: clk +Description: "clock" +Direction: in +Default_Type: d +Allowed_Types: [d] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PORT_TABLE: + +Port_Name: set reset +Description: "asynch. set" "asynch. reset" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PORT_TABLE: + +Port_Name: out Nout +Description: "data output" "inverted data output" +Direction: out out +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: clk_delay set_delay +Description: "delay from clk" "delay from set" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: reset_delay ic +Description: "delay from reset" "output initial state" +Data_Type: real int +Default_Value: 1.0e-9 0 +Limits: [1e-12 -] [0 2] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "rise delay" "fall delay" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: jk_load clk_load +Description: "j,k load values (F)" "clk load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: set_load reset_load +Description: "set load value (F)" "reset load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + diff --git a/src/xspice/icm/digital/d_nand/cfunc.mod b/src/xspice/icm/digital/d_nand/cfunc.mod new file mode 100644 index 000000000..a2722d90d --- /dev/null +++ b/src/xspice/icm/digital/d_nand/cfunc.mod @@ -0,0 +1,242 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_nand/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 18 June 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the d_nand + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + +/*============================================================================== + +FUNCTION cm_d_nand() + +AUTHORS + + 18 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_nand code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_NAND ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital NAND gate for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/18/91 J.P.Murray * +************************************************/ + + +void cm_d_nand(ARGS) + +{ + int i, /* generic loop counter index */ + size; /* number of input & output ports */ + + + + Digital_State_t *out, /* temporary output for buffers */ + *out_old, /* previous output for buffers */ + input; /* temp storage for input bits */ + + + /** Retrieve size value... **/ + size = PORT_SIZE(in); + + + + /*** Setup required state variables ***/ + + if(INIT) { /* initial pass */ + + /* allocate storage for the outputs */ + out = out_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + + for (i=0; i * +* I * +* I t2 t3 * +* I \______________/_____ * +* I | | * +* I | | | | * +* I | | * +* I | | | | * +* I | | * +* I | | | | * +* I-----------------*-----* - - - - - - - - - -*--------- * +* t1 t4 * +* * +* * +* t2 = t1 + rise_delay * +* t4 = t3 + fall_delay * +* * +* Note that for the digital model, unlike for the * +* analog "square" model, t1 and t3 are stored and * +* adjusted values, but t2 & t4 are implied by the * +* rise and fall delays of the model, but are otherwise * +* not stored values. JPM * +* * +*************************************************************/ + +void cm_d_osc(ARGS) +{ + + double *x, /* analog input value control array */ + *y, /* frequency array */ + cntl_input, /* control input value */ + *phase, /* instantaneous phase of the model */ + *phase_old, /* previous phase of the model */ + *t1, /* pointer to t1 value */ + *t3, /* pointer to t3 value */ + time1, /* variable for calculating new time1 value */ + time3, /* variable for calculating new time3 value */ + freq, /* instantaneous frequency value */ + dphase, /* fractional part into cycle */ + duty_cycle, /* duty_cycle value */ + test_double, /* testing variable */ + slope; /* slope value...used to extrapolate + freq values past endpoints. */ + + + int i, /* generic loop counter index */ + cntl_size, /* control array size */ + freq_size, /* frequency array size */ + int_cycle; /* integer number of cycles */ + + + + + + + /**** Retrieve frequently used parameters... ****/ + + cntl_size = PARAM_SIZE(cntl_array); + freq_size = PARAM_SIZE(freq_array); + duty_cycle = PARAM(duty_cycle); + + + /* check and make sure that the control array is the + same size as the frequency array */ + + if(cntl_size != freq_size){ + cm_message_send(d_osc_array_error); + return; + } + + + if (INIT) { /*** Test for INIT == TRUE. If so, allocate storage, etc. ***/ + + + /* Allocate storage for internal variables */ + phase = phase_old = cm_analog_alloc(0,sizeof(double)); + + t1 = cm_analog_alloc(1,sizeof(double)); + + t3 = cm_analog_alloc(2,sizeof(double)); + + + } + + else { /*** This is not an initialization pass...retrieve storage + addresses and calculate new outputs, if required. ***/ + + + /** Retrieve previous values... **/ + + + /* assign internal variables */ + phase = cm_analog_get_ptr(0,0); + phase_old = cm_analog_get_ptr(0,1); + + t1 = cm_analog_get_ptr(1,0); + + t3 = cm_analog_get_ptr(2,0); + + } + + + + + switch (CALL_TYPE) { + + case ANALOG: /** analog call **/ + + test_double = TIME; + + if ( AC == ANALYSIS ) { /* this model does not function + in AC analysis mode. */ + + return; + + } + else { + + if ( 0.0 == TIME ) { /* DC analysis */ + + /* retrieve & normalize phase value */ + *phase = PARAM(init_phase); + if ( 0 > *phase ) { + *phase = *phase + 360.0; + } + *phase = *phase / 360.0; + + + /* set phase value to init_phase */ + *phase_old = *phase; + + /* preset time values to harmless values... */ + *t1 = -1; + *t3 = -1; + + + } + + + /* Allocate storage for breakpoint domain & freq. range values */ + + x = (double *) calloc(cntl_size, sizeof(double)); + if (x == '\0') { + cm_message_send(d_osc_allocation_error); + return; + } + + y = (double *) calloc(freq_size, sizeof(double)); + if (y == '\0') { + cm_message_send(d_osc_allocation_error); + return; + } + + /* Retrieve x and y values. */ + for (i=0; i= x[cntl_size-1]) { + + slope = (y[cntl_size-1] - y[cntl_size-2]) / + (x[cntl_size-1] - x[cntl_size-2]); + freq = y[cntl_size-1] + (cntl_input - x[cntl_size-1]) * slope; + + } + else { /*** cntl_input within bounds of end midpoints... + must determine position progressively & then + calculate required output. ***/ + + for (i=0; i= x[i]) ) { + + /* Interpolate to the correct frequency value */ + + freq = ( (cntl_input - x[i]) / (x[i+1] - x[i]) ) * + ( y[i+1]-y[i] ) + y[i]; + } + } + } + + /*** If freq < 0.0, clamp to 1e-16 & issue a warning ***/ + if ( 0.0 > freq ) { + freq = 1.0e-16; + cm_message_send(d_osc_negative_freq_error); + } + + + /* calculate the instantaneous phase */ + *phase = *phase_old + freq * (TIME - T(1)); + + /* convert the phase to an integer */ + int_cycle = *phase_old; + + /* dphase is the percent into the cycle for + the period */ + dphase = *phase_old - int_cycle; + + + /* Calculate the time variables and the output value + for this iteration */ + + if((*t1 <= TIME) && (TIME <= *t3)) { /* output high */ + + *t3 = T(1) + (1 - dphase)/freq; + + if(TIME < *t3) { + cm_event_queue(*t3); + } + + + } + else + + if((*t3 <= TIME) && (TIME <= *t1)) { /* output low */ + + if(dphase > (1.0 - duty_cycle) ) { + dphase = dphase - 1.0; + } + *t1 = T(1) + ( (1.0 - duty_cycle) - dphase)/freq; + + if(TIME < *t1) { + + cm_event_queue(*t1); + + } + } + else { + + if(dphase > (1.0 - duty_cycle) ) { + dphase = dphase - 1.0; + } + *t1 = T(1) + ( (1.0 - duty_cycle) - dphase )/freq; + + if((TIME < *t1) || (T(1) == 0)) { + cm_event_queue(*t1); + } + + *t3 = T(1) + (1 - dphase)/freq; + + + } + + + + free(x); + free(y); + + + } + break; + + + case EVENT: /** discrete call...lots to do **/ + + + test_double = TIME; + + if ( 0.0 == TIME ) { /* DC analysis...preset values, + as appropriate.... */ + + /* retrieve & normalize phase value */ + *phase = PARAM(init_phase); + if ( 0 > *phase ) { + *phase = *phase + 360.0; + } + *phase = *phase / 360.0; + + + /* set phase value to init_phase */ + *phase_old = *phase; + + /* preset time values to harmless values... */ + *t1 = -1; + *t3 = -1; + } + + + + /* Calculate the time variables and the output value + for this iteration */ + + /* Output is always set to STRONG */ + OUTPUT_STRENGTH(out) = STRONG; + + + + if( *t1 == TIME ) { /* rising edge */ + + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(rise_delay); + + } + else { + + if ( *t3 == TIME ) { /* falling edge */ + + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(fall_delay); + } + + else { /* no change in output */ + + if ( TIME != 0.0 ) { + OUTPUT_CHANGED(out) = FALSE; + } + + if ( (*t1 < TIME) && (TIME < *t3) ) { + OUTPUT_STATE(out) = ONE; + } + else { + OUTPUT_STATE(out) = ZERO; + } + } + } + + break; + + } +} + + + + + + + diff --git a/src/xspice/icm/digital/d_osc/d_osc.h b/src/xspice/icm/digital/d_osc/d_osc.h new file mode 100644 index 000000000..16b1ebf5f --- /dev/null +++ b/src/xspice/icm/digital/d_osc/d_osc.h @@ -0,0 +1,91 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_osc/d_osc.h + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 25 Jul 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the header information for the d_osc + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + + +REFERENCED FILES + + N/A + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ +/* + Structures, etc. for d_osc oscillator model. + 7/25/90 + Last Modified 7/25/91 J.P.Murray */ + +/*=======================================================================*/ + +/*=== INCLUDE FILES =====================================================*/ + +#include +#include +#include +#include + + + + +/*=== CONSTANTS =========================================================*/ + + +/**** Error Messages ****/ +char *d_osc_allocation_error = "\n**** Error ****\nD_OSC: Error allocating VCO block storage \n"; +char *d_osc_array_error = "\n**** Error ****\nD_OSC: Size of control array different than frequency array \n"; +char *d_osc_negative_freq_error = "\n**** Error ****\nD_OSC: The extrapolated value for frequency\nhas been found to be negative... \n Lower frequency level has been clamped to 0.0 Hz \n"; + + + + + + +/*=== MACROS ============================================================*/ + + + +/*=== LOCAL VARIABLES & TYPEDEFS ========================================*/ + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ====================================*/ + + +/*=======================================================================*/ + + diff --git a/src/xspice/icm/digital/d_osc/ifspec.ifs b/src/xspice/icm/digital/d_osc/ifspec.ifs new file mode 100644 index 000000000..cd1427833 --- /dev/null +++ b/src/xspice/icm/digital/d_osc/ifspec.ifs @@ -0,0 +1,74 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + hybrid d_osc code model. + +===============================================================================*/ + +NAME_TABLE: + +Spice_Model_Name: d_osc +C_Function_Name: cm_d_osc +Description: "controlled digital oscillator" + + +PORT_TABLE: + +Port_Name: cntl_in out +Description: "control input" "output" +Direction: in out +Default_Type: v d +Allowed_Types: [v,vd,i,id] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + + +PARAMETER_TABLE: + +Parameter_Name: cntl_array freq_array +Description: "control array" "frequency array" +Data_Type: real real +Default_Value: 0.0 1.0e6 +Limits: - [0 -] +Vector: yes yes +Vector_Bounds: [2 -] [2 -] +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: duty_cycle init_phase +Description: "output duty cycle" "initial phase of output" +Data_Type: real real +Default_Value: 0.5 0 +Limits: [1e-6 0.999999] [-180.0 +360.0] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "rise delay" "fall delay" +Data_Type: real real +Default_Value: 1e-9 1e-9 +Limits: [0 -] [0 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + diff --git a/src/xspice/icm/digital/d_pulldown/cfunc.mod b/src/xspice/icm/digital/d_pulldown/cfunc.mod new file mode 100644 index 000000000..d55fad74f --- /dev/null +++ b/src/xspice/icm/digital/d_pulldown/cfunc.mod @@ -0,0 +1,134 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_pulldown/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 19 Nov 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 19 Nov 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the d_pulldown + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_d_pulldown() + +AUTHORS + + 19 Nov 1991 Jeffrey P. Murray + +MODIFICATIONS + + 19 Nov 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_pulldown code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_PULLDOWN ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital pulldown resistor for the * +* ATESSE Version 2.0 system. * +* * +* Created 11/19/91 J.P,Murray * +************************************************/ + + +void cm_d_pulldown(ARGS) + +{ + LOAD(out) = PARAM(load); + OUTPUT_STATE(out) = ZERO; + OUTPUT_STRENGTH(out) = RESISTIVE; +} + + + + diff --git a/src/xspice/icm/digital/d_pulldown/ifspec.ifs b/src/xspice/icm/digital/d_pulldown/ifspec.ifs new file mode 100644 index 000000000..c6cbe0216 --- /dev/null +++ b/src/xspice/icm/digital/d_pulldown/ifspec.ifs @@ -0,0 +1,51 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 19 Nov 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_pulldown code model. + +===============================================================================*/ + + +NAME_TABLE: + +Spice_Model_Name: d_pulldown +C_Function_Name: cm_d_pulldown +Description: "digital pulldown resistor" + + +PORT_TABLE: + +Port_Name: out +Description: "output" +Direction: out +Default_Type: d +Allowed_Types: [d] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + +Parameter_Name: load +Description: "load value (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + diff --git a/src/xspice/icm/digital/d_pullup/cfunc.mod b/src/xspice/icm/digital/d_pullup/cfunc.mod new file mode 100644 index 000000000..d3a273ccb --- /dev/null +++ b/src/xspice/icm/digital/d_pullup/cfunc.mod @@ -0,0 +1,130 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_pullup/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 19 Nov 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 19 Nov 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the d_pullup + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_d_pullup() + +AUTHORS + + 19 Nov 1991 Jeffrey P. Murray + +MODIFICATIONS + + 19 Nov 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_pullup code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_PULLUP ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital pullup resistor for the * +* ATESSE Version 2.0 system. * +* * +* Created 11/19/91 J.P,Murray * +************************************************/ + + +void cm_d_pullup(ARGS) + +{ + LOAD(out) = PARAM(load); + OUTPUT_STATE(out) = ONE; + OUTPUT_STRENGTH(out) = RESISTIVE; +} diff --git a/src/xspice/icm/digital/d_pullup/ifspec.ifs b/src/xspice/icm/digital/d_pullup/ifspec.ifs new file mode 100644 index 000000000..0d5a1b6fe --- /dev/null +++ b/src/xspice/icm/digital/d_pullup/ifspec.ifs @@ -0,0 +1,51 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 19 Nov 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_pullup code model. + +===============================================================================*/ + + +NAME_TABLE: + +Spice_Model_Name: d_pullup +C_Function_Name: cm_d_pullup +Description: "digital pullup resistor" + + +PORT_TABLE: + +Port_Name: out +Description: "output" +Direction: out +Default_Type: d +Allowed_Types: [d] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + +Parameter_Name: load +Description: "load value (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + diff --git a/src/xspice/icm/digital/d_ram/cfunc.mod b/src/xspice/icm/digital/d_ram/cfunc.mod new file mode 100644 index 000000000..8be72e966 --- /dev/null +++ b/src/xspice/icm/digital/d_ram/cfunc.mod @@ -0,0 +1,1179 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_ram/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 23 Aug 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the d_ram code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include +#include +#include +#include + + + +/*=== CONSTANTS ========================*/ + +#define MASK0 0x0003 +#define MASK1 0x000c +#define MASK2 0x0030 +#define MASK3 0x00c0 +#define MASK4 0x0300 +#define MASK5 0x0c00 +#define MASK6 0x3000 +#define MASK7 0xc000 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_address_to_decimal() + +AUTHORS + + 27 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 8 Jul 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + Calculates a decimal value from binary values passed. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + A pointer containing the total (*total). + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_ADDRESS_TO_DECIMAL ROUTINE ===*/ + +/************************************************ +* The following routine calculates a * +* decimal value equivalent to the binary * +* value passed to it on address[i] bits. * +* The determined value is written to the * +* integer *total. * +* * +* Created 6/27/91 J.P.Murray * +************************************************/ + + +static int cm_address_to_decimal(Digital_State_t *address,int address_size,int *total) +{ + int i, /* indexing variable */ + multiplier, /* binary multiplier value */ + err; /* error value: 1 => output is unknown + 0 => output is valid */ + + err = 0; + *total = 0; + multiplier = 1; + + for (i=0; i>1; + } + + + + + + + + /******* Determine analysis type and output appropriate values *******/ + + if (0.0 == TIME) { /****** DC analysis...output w/o delays ******/ + + /** initialize ram to ic value **/ + + out = PARAM(ic); + for (i=0; i code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + int cm_event_queue() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include "d_source.h" /* ...contains macros & type defns. + for this model. 6/13/90 - JPM */ + + + +/*=== CONSTANTS ========================*/ + +#define MAX_STRING_SIZE 200 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + +typedef struct { + int index, /* current index into source tables */ + width, /* width of table...equal to size of out port */ + depth; /* depth of table...equal to size of + "timepoints" array, and to the total + number of vectors retrieved from the + source.in file. */ +} Source_Table_Info_t; + + + + + +/* Type definition for each possible token returned. */ +typedef enum token_type_s {CNV_NO_TOK,CNV_STRING_TOK} Cnv_Token_Type_t; + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + +/*============================================================================== + +FUNCTION *CNVgettok() + +AUTHORS + + 13 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 8 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function obtains the next token from an input stream. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + +RETURNED VALUE + + Returns a string value representing the next token. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CNVgettok ROUTINE ================*/ +/* +Get the next token from the input string. The input string pointer +is advanced to the following token and the token from the input +string is copied to malloced storage and a pointer to that storage +is returned. The original input string is undisturbed. +*/ + +static char *CNVgettok(char **s) + +{ + + char *buf; /* temporary storage to copy token into */ + char *temp; /* temporary storage to copy token into */ + char *ret_str; /* storage for returned string */ + + int i; + + /* allocate space big enough for the whole string */ + + buf = (void *) malloc(strlen(*s) + 1); + + /* skip over any white space */ + + while(isspace(**s) || (**s == '=') || + (**s == '(') || (**s == ')') || (**s == ',')) + (*s)++; + + /* isolate the next token */ + + switch(**s) { + + case '\0': /* End of string found */ + free(buf); + return(NULL); + + + default: /* Otherwise, we are dealing with a */ + /* string representation of a number */ + /* or a mess o' characters. */ + i = 0; + while( (**s != '\0') && + (! ( isspace(**s) || (**s == '=') || + (**s == '(') || (**s == ')') || + (**s == ',') + ) ) ) { + buf[i] = **s; + i++; + (*s)++; + } + buf[i] = '\0'; + break; + } + + /* skip over white space up to next token */ + + while(isspace(**s) || (**s == '=') || + (**s == '(') || (**s == ')') || (**s == ',')) + (*s)++; + + /* make a copy using only the space needed by the string length */ + + + ret_str = (void *) malloc(strlen(buf) + 1); + ret_str = strcpy(ret_str,buf); + + free(buf); + + return(ret_str); +} + + +/*============================================================================== + +FUNCTION *CNVget_token() + +AUTHORS + + 13 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 8 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function obtains the next token from an input stream. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + +RETURNED VALUE + + Returns a string value representing the next token. Uses + *CNVget_tok. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CNVget_token ROUTINE =============*/ +/* +Get the next token from the input string together with its type. +The input string pointer +is advanced to the following token and the token from the input +string is copied to malloced storage and a pointer to that storage +is returned. The original input string is undisturbed. +*/ + +static char *CNVget_token(char **s, Cnv_Token_Type_t *type) + +{ + + char *ret_str; /* storage for returned string */ + + /* get the token from the input line */ + + ret_str = CNVgettok(s); + + + /* if no next token, return */ + + if(ret_str == NULL) { + *type = CNV_NO_TOK; + return(NULL); + } + + /* else, determine and return token type */ + + switch(*ret_str) { + + default: + *type = CNV_STRING_TOK; + break; + + } + + return(ret_str); +} + + + + +/*============================================================================== + +FUNCTION cnv_get_spice_value() + +AUTHORS + + ??? Bill Kuhn + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function takes as input a string token from a SPICE + deck and returns a floating point equivalent value. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + +RETURNED VALUE + + Returns the floating point value in pointer *p_value. Also + returns an integer representing successful completion. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CNV_get_spice_value ROUTINE =============*/ + +/* + Function takes as input a string token from a SPICE +deck and returns a floating point equivalent value. +*/ + + +static int cnv_get_spice_value(str,p_value) + +char *str; /* IN - The value text e.g. 1.2K */ +float *p_value; /* OUT - The numerical value */ +{ + + + /* the following were "int4" devices - jpm */ + int len; + int i; + int n_matched; + + line_t val_str; + + char *suffix; + char c; + char c1; + + float scale_factor; + float value; + + + /* Scan the input string looking for an alpha character that is not */ + /* 'e' or 'E'. Such a character is assumed to be an engineering */ + /* suffix as defined in the Spice 2G.6 user's manual. */ + + len = strlen(str); + if( len > (sizeof(val_str) - 1)) + len = sizeof(val_str) - 1; + + for(i = 0; i < len; i++) { + c = str[i]; + if( isalpha(c) && (c != 'E') && (c != 'e') ) + break; + else if( isspace(c) ) + break; + else + val_str[i] = c; + } + val_str[i] = '\0'; + + + /* Determine the scale factor */ + + if( (i >= len) || (! isalpha(c)) ) + scale_factor = 1.0; + else { + + if(isupper(c)) + c = tolower(c); + + switch(c) { + + case 't': + scale_factor = 1.0e12; + break; + + case 'g': + scale_factor = 1.0e9; + break; + + case 'k': + scale_factor = 1.0e3; + break; + + case 'u': + scale_factor = 1.0e-6; + break; + + case 'n': + scale_factor = 1.0e-9; + break; + + case 'p': + scale_factor = 1.0e-12; + break; + + case 'f': + scale_factor = 1.0e-15; + break; + + case 'm': + i++; + if(i >= len) { + scale_factor = 1.0e-3; + break; + } + c1 = str[i]; + if(! isalpha(c1)) { + scale_factor = 1.0e-3; + break; + } + if(islower(c1)) + c1 = toupper(c1); + if(c1 == 'E') + scale_factor = 1.0e6; + else if(c1 == 'I') + scale_factor = 25.4e-6; + else + scale_factor = 1.0e-3; + break; + + default: + scale_factor = 1.0; + } + } + + /* Convert the numeric portion to a float and multiply by the */ + /* scale factor. */ + + n_matched = sscanf(val_str,"%e",&value); + + if(n_matched < 1) { + *p_value = 0.0; + return(FAIL); + } + + *p_value = value * scale_factor; + return(OK); +} + + + + + +/*============================================================================== + +FUNCTION cm_source_mask_and_retrieve() + +AUTHORS + + 15 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 16 Jul 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + Masks off and retrieves a two-bit value from a short + integer word passed to the function, using an offset value. + This effectively handles retrieval of eight two-bit values + from a single short integer space in order to conserve memory. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns a Digital_t value. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_SOURCE_MASK_AND_RETRIEVE ROUTINE ===*/ + +/************************************************** +* The following routine masks and retrieves * +* the value passed to it by the out value * +* by masking the appropriate bits in the * +* base integer. The particular bit affected * +* is determined by the bit_offset value. * +* * +* Created 7/15/91 J.P.Murray * +**************************************************/ + +static void cm_source_mask_and_retrieve(short base,int bit_offset,Digital_t *out) +{ + + + short value; /* the hexadecimal value of the masked bit */ + + + + switch (bit_offset) { + case 0: + break; + + case 1: + base = base >> 4; + break; + + case 2: + base = base >> 8; + break; + + case 3: + base = base >> 12; + break; + } + + + value = 0x000f & base; + + + switch (value) { + + case 0: out->state = ZERO; + out->strength = STRONG; + break; + + case 1: out->state = ONE; + out->strength = STRONG; + break; + + case 2: out->state = UNKNOWN; + out->strength = STRONG; + break; + + case 3: out->state = ZERO; + out->strength = RESISTIVE; + break; + + case 4: out->state = ONE; + out->strength = RESISTIVE; + break; + + case 5: out->state = UNKNOWN; + out->strength = RESISTIVE; + break; + + case 6: out->state = ZERO; + out->strength = HI_IMPEDANCE; + break; + + case 7: out->state = ONE; + out->strength = HI_IMPEDANCE; + break; + + case 8: out->state = UNKNOWN; + out->strength = HI_IMPEDANCE; + break; + + case 9: out->state = ZERO; + out->strength = UNDETERMINED; + break; + + case 10: out->state = ONE; + out->strength = UNDETERMINED; + break; + + case 11: out->state = UNKNOWN; + out->strength = UNDETERMINED; + break; + } +} + + +/*============================================================================== + +FUNCTION cm_source_mask_and_store() + +AUTHORS + + 15 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 16 Jul 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + Masks off and stores a two-bit value to a short + integer word passed to the function, using an offset value. + This effectively handles storage of eight two-bit values + to a single short integer space in order to conserve memory. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns updated *base value. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_SOURCE_MASK_AND_STORE ROUTINE ===*/ + +/************************************************ +* The following routine masks and stores * +* the value passed to it by the out value * +* by masking the appropriate bits in the * +* base integer. The particular bit affected * +* is determined by the ram_offset value. * +* * +* Created 7/15/91 J.P.Murray * +************************************************/ + +static int cm_source_mask_and_store(short *base,int bit_offset,int bit_value) +{ + switch (bit_offset) { + case 0: + *base = *base & 0xfff0; + break; + + case 1: + *base = *base & 0xff0f; + bit_value = bit_value << 4; + break; + + case 2: + *base = *base & 0xf0ff; + bit_value = bit_value << 8; + break; + + case 3: + *base = *base & 0x0fff; + bit_value = bit_value << 12; + break; + } + + *base = *base | bit_value; +} + + + + +/*============================================================================== + +FUNCTION cm_get_source_value() + +AUTHORS + + 15 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 16 Jul 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + Retrieves four-bit data from short integer array "source". + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns data via *out pointer. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_GET_SOURCE_VALUE ROUTINE ===*/ + +/************************************************ +* The following routine retrieves four-bit * +* data from short integer array "source". The * +* integers are assumed to be at least two * +* bytes each, so each will hold four four- * +* bit values. * +* * +* Created 7/15/91 J.P.Murray * +************************************************/ + +static void cm_get_source_value(int word_width,int bit_number,int index, + short *bits, Digital_t *out) + +{ + int err, /* error index value */ + int1, /* temp storage variable */ + bit_index, /* bits base address at which word bits will + be found */ + bit_offset; /* offset from ram base address at which bit[0] + of the required word can be found */ + + short base; /* variable to hold current base integer for + comparison purposes. */ + + double double1, + double2; /* holding variables for modf routine */ + + + + /* obtain offset value from index, word_width & bit_number */ + int1 = index * word_width + bit_number; + double1 = int1 / 4.0; + modf(double1, &double2); + bit_index = double2; + bit_offset = int1 - (double2 * 4.0); + + /* retrieve entire base_address bits integer... */ + base = bits[bit_index]; + + /* for each offset, mask off the bits and determine values */ + + cm_source_mask_and_retrieve(base,bit_offset,out); + +} + + + +/*============================================================================== + +FUNCTION cm_read_source() + +AUTHORS + + 15 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 19 Jul 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function reads the source file and stores the results + for later output by the model. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns output bits stored in "bits" array. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_READ_SOURCE ROUTINE ===*/ + + +/************************************************** +* The following routine reads the file * +* *source, parses the file, and stores * +* the values found there into the *bits & * +* *timepoints arrays. * +* * +* Created 7/15/91 J.P.Murray * +**************************************************/ + +static int cm_read_source(FILE *source,short *bits,double *timepoints, + Source_Table_Info_t *info) +{ + int i, /* indexing variable */ + j, /* indexing variable */ + num_tokens, /* number of tokens in a given string */ + bit_index, /* index to which bits[] integer we are accessing */ + bit_offset, /* index to which bit within the current bits[] + integer we are accessing */ + int1; /* temporary holding variable */ + + + Cnv_Token_Type_t type; /* variable for testing token type returned. */ + + + char temp[MAX_STRING_SIZE], /* holding string variable for testing + input from source.in */ + *s, /* main string variable */ + *base_address, /* storage location for base address + of string. */ + *token; /* a particular token from the string */ + + + float number; /* holding variable for timepoint values */ + + double double1, /* temporary holding variable */ + double2; /* temporary holding variable */ + + short bit_value, /* holding variable for value read from + source file which needs to be stored */ + base; /* holding variable for existing + non-masked bits[] integer */ + + i = 0; + s = temp; + while ( fgets(s,MAX_STRING_SIZE,source) != NULL) { + + /* Test this string to see if it is whitespace... */ + + base_address = s; + while(isspace(*s) || (*s == '*')) + (s)++; + if ( *s != '\0' ) { /* This is not a blank line, so process... */ + s = base_address; + + if ( '*' != s[0] ) { + + /* Count up total number of tokens including \0... */ + j = 0; + type = CNV_STRING_TOK; + while ( type != CNV_NO_TOK ) { + token = CNVget_token(&s, &type); + j++; + } + num_tokens = j; + + /* If this number is incorrect, return with an error */ + if ( (info->width + 2) != num_tokens) { + return 1; + } + + /* reset s to beginning... */ + s = base_address; + + /** Retrieve each token, analyze, and **/ + /** store the timepoint and bit information **/ + for (j=0; j<(info->width + 1); j++) { + + token = CNVget_token(&s, &type); + + if ( 0 == j ) { /* obtain timepoint value... */ + + /* convert to a floating point number... */ + cnv_get_spice_value(token,&number); + + timepoints[i] = number; + + + /* provided this is not the first timepoint + to be written... */ + if ( 0 != i ) { + + /* if current timepoint value is not greater + than the previous value, then return with + an error message... */ + if ( timepoints[i] <= timepoints[i-1] ) { + return 1; + } + } + + } + else { /* obtain each bit value & set bits entry */ + + /* preset this bit location */ + bit_value = 12; + + if (0 == strcmp(token,"0s")) bit_value = 0; + if (0 == strcmp(token,"1s")) bit_value = 1; + if (0 == strcmp(token,"Us")) bit_value = 2; + if (0 == strcmp(token,"0r")) bit_value = 3; + if (0 == strcmp(token,"1r")) bit_value = 4; + if (0 == strcmp(token,"Ur")) bit_value = 5; + if (0 == strcmp(token,"0z")) bit_value = 6; + if (0 == strcmp(token,"1z")) bit_value = 7; + if (0 == strcmp(token,"Uz")) bit_value = 8; + if (0 == strcmp(token,"0u")) bit_value = 9; + if (0 == strcmp(token,"1u")) bit_value = 10; + if (0 == strcmp(token,"Uu")) bit_value = 11; + + /* if this bit was not recognized, return with an error */ + if (12 == bit_value) { + return 1; + } + else { /* need to store this value in the bits[] array */ + + /* obtain offset value from word_number, word_width & + bit_number */ + int1 = i * info->width + (j-1); + double1 = int1 / 4.0; + modf(double1, &double2); + bit_index = double2; + bit_offset = int1 - (double2 * 4.0); + + /* retrieve entire base_address bits integer... */ + base = bits[bit_index]; + + /* for each offset, mask off the bits and store values */ + cm_source_mask_and_store(&base,bit_offset,bit_value); + + /* store modified base value */ + bits[bit_index] = base; + } + } + } + i++; + } + s = temp; + } + } + return 0; +} + + + + + +/*============================================================================== + +FUNCTION cm_d_source() + +AUTHORS + + 13 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 8 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_source code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + int cm_event_queue() + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_SOURCE ROUTINE ==============*/ + +/************************************************ +* The following is the model for the * +* digital source for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/13/91 J.P.Murray * +************************************************/ + + +void cm_d_source(ARGS) +{ + int i, /* generic loop counter index */ + err, /* integer for storage of error status */ + test, /* testing integer */ + dummy; /* temp holding variable */ + + + short *bits, /* the storage array for the + output bit representations... + this will have size equal to + (width * depth)/4, since one + short will hold four 12-state + bit descriptions. */ + *bits_old; /* the storage array for old bit values */ + + + double *timepoints, /* the storage array for the + timepoints...this will have size equal + to "depth" */ + *timepoints_old, /* the storage array for the old timepoints */ + test_double, /* test variable for doubles */ + double_dummy; /* fake holding double */ + + + + FILE *source; /* pointer to the source.in input + vector file */ + + + Source_Table_Info_t *info, /* storage location for source + index and depth info. */ + *info_old; /* storage location for old info */ + + + Digital_t out; /* storage for each output bit */ + + + + char temp[MAX_STRING_SIZE], /* holding string variable for testing + input from source.in */ + *s; /* main string variable */ + + + char *loading_error = "\n***ERROR***\nD_SOURCE: source.in file was not read successfully. \n"; + + + + + + /**** Setup required state variables ****/ + + if(INIT) { /* initial pass */ + + + + /*** open file and count the number of vectors in it ***/ + source = fopen( PARAM(input_file), "r"); + + /* increment counter if not a comment until EOF reached... */ + i = 0; + s = temp; + while ( fgets(s,MAX_STRING_SIZE,source) != NULL) { + if ( '*' != s[0] ) { + while(isspace(*s) || (*s == '*')) + (s)++; + if ( *s != '\0' ) i++; + } + s = temp; + } + + /*** allocate storage for *index, *bits & *timepoints ***/ + + info = info_old = (Source_Table_Info_t *) + cm_event_alloc(0,sizeof(Source_Table_Info_t)); + + + + modf( (PORT_SIZE(out) * i / 4), &double_dummy ); + dummy = double_dummy + 1; + + bits = bits_old = (short *) cm_event_alloc(1,(dummy * sizeof(short))); + + timepoints = timepoints_old = (double *) + cm_event_alloc(2,i * sizeof(double)); + + + /**** Patch assignment for memory...remove in final version ****/ + info = info_old = (Source_Table_Info_t *) cm_event_get_ptr(0,0); + bits = bits_old = (short *) cm_event_get_ptr(1,0); + timepoints = timepoints_old = (double *) cm_event_get_ptr(2,0); + + + + + /* Initialize info values... */ + + info->index = 0; + info->depth = i; + + /* Retrieve width of the source */ + info->width = PORT_SIZE(out); + + + /* Initialize *bits & *timepoints to zero */ + + for (i=0; idepth; i++) timepoints[i] = 0; + + + + + + + /* Send file pointer and the two array storage pointers */ + /* to "cm_read_source()". This will return after */ + /* reading the contents of source.in, and if no */ + /* errors have occurred, the "*bits" and "*timepoints" */ + /* vectors will be loaded and the width and depth */ + /* values supplied. */ + + rewind(source); + err = cm_read_source(source,bits,timepoints,info); + + + + + if (err) { /* problem occurred in load...send error msg. */ + + cm_message_send(loading_error); + + /* Reset *bits & *timepoints to zero */ + for (i=0; i<(test = (info->width*info->depth)/4); i++) bits[i] = 0; + for (i=0; idepth; i++) timepoints[i] = 0; + } + + /* close source file */ + fclose(source); + + } + else { /*** Retrieve previous values ***/ + + /** Retrieve info... **/ + info = (Source_Table_Info_t *) cm_event_get_ptr(0,0); + info_old = (Source_Table_Info_t *) cm_event_get_ptr(0,1); + + /* Set old values to new... */ + info->index = info_old->index; + info->depth = info_old->depth; + info->width = info_old->width; + + + + /** Retrieve bits... **/ + bits = (short *) cm_event_get_ptr(1,0); + bits_old = (short *) cm_event_get_ptr(1,1); + + /* Set old values to new... */ + modf( (info->width * info->depth / 4), &double_dummy ); + dummy = double_dummy + 1; + + + for (i=0; idepth; i++) + timepoints[i] = timepoints_old[i]; + + + } + + /*** For the case of TIME==0.0, set special breakpoint ***/ + + if ( 0.0 == TIME ) { + + test_double = timepoints[info->index]; + if ( 0.0 == test_double ) { /* Set DC value */ + + /* reset current breakpoint */ + test_double = timepoints[info->index]; + cm_event_queue( test_double ); + + /* Output new values... */ + for (i=0; iwidth; i++) { + + /* retrieve output value */ + cm_get_source_value(info->width,i,info->index,bits,&out); + + OUTPUT_STATE(out[i]) = out.state; + OUTPUT_STRENGTH(out[i]) = out.strength; + } + + /* increment breakpoint */ + (info->index)++; + + + /* set next breakpoint as long as depth + has not been exceeded */ + if ( info->index < info->depth ) { + test_double = timepoints[info->index] - 1.0e-10; + cm_event_queue( test_double ); + } + + } + else { /* Set breakpoint for first time index */ + + /* set next breakpoint as long as depth + has not been exceeded */ + if ( info->index < info->depth ) { + test_double = timepoints[info->index] - 1.0e-10; + cm_event_queue( test_double ); + } + } + } + else { + + /*** Retrieve last index value and branch to appropriate *** + *** routine based on the last breakpoint's relationship *** + *** to the current time value. ***/ + + test_double = timepoints[info->index] - 1.0e-10; + + if ( TIME < test_double ) { /* Breakpoint has not occurred */ + + /** Output hasn't changed...do nothing this time. **/ + for (i=0; iwidth; i++) { + OUTPUT_CHANGED(out[i]) = FALSE; + } + + if ( info->index < info->depth ) { + test_double = timepoints[info->index] - 1.0e-10; + cm_event_queue( test_double ); + } + + } + else /* Breakpoint has been reached or exceeded */ + + if ( TIME == test_double ) { /* Breakpoint reached */ + + /* reset current breakpoint */ + test_double = timepoints[info->index] - 1.0e-10; + cm_event_queue( test_double ); + + /* Output new values... */ + for (i=0; iwidth; i++) { + + /* retrieve output value */ + cm_get_source_value(info->width,i,info->index,bits,&out); + + OUTPUT_STATE(out[i]) = out.state; + OUTPUT_DELAY(out[i]) = 1.0e-10; + OUTPUT_STRENGTH(out[i]) = out.strength; + } + + + + /* increment breakpoint */ + (info->index)++; + + + /* set next breakpoint as long as depth + has not been exceeded */ + if ( info->index < info->depth ) { + test_double = timepoints[info->index] - 1.0e-10; + cm_event_queue( test_double ); + } + + + + } + + else { /* Last source file breakpoint has been exceeded... + do not change the value of the output */ + + for (i=0; iwidth; i++) { + OUTPUT_CHANGED(out[i]) = FALSE; + } + } + } +} + + + diff --git a/src/xspice/icm/digital/d_source/d_source.h b/src/xspice/icm/digital/d_source/d_source.h new file mode 100644 index 000000000..856a54243 --- /dev/null +++ b/src/xspice/icm/digital/d_source/d_source.h @@ -0,0 +1,83 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_source/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 13 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 8 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the header information used by the + d_source code model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + + +REFERENCED FILES + + NONE + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include +#include +#include +#include + + + +/*=== CONSTANTS ========================*/ + +#define OK 0 +#define FAIL 1 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + +typedef char line_t[82]; /* A SPICE size line. <= 80 characters plus '\n\0' */ + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*=============================================================================*/ diff --git a/src/xspice/icm/digital/d_source/ifspec.ifs b/src/xspice/icm/digital/d_source/ifspec.ifs new file mode 100644 index 000000000..2fc841963 --- /dev/null +++ b/src/xspice/icm/digital/d_source/ifspec.ifs @@ -0,0 +1,65 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_source code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_d_source +Spice_Model_Name: d_source +Description: "digital signal source" + + +PORT_TABLE: + + +Port_Name: out +Description: "output" +Direction: out +Default_Type: d +Allowed_Types: [d] +Vector: yes +Vector_Bounds: - +Null_Allowed: no + + + +PARAMETER_TABLE: + + +Parameter_Name: input_file +Description: "digital input vector filename" +Data_Type: string +Default_Value: "source.txt" +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + + +Parameter_Name: input_load +Description: "input loading capacitance (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: no diff --git a/src/xspice/icm/digital/d_srff/cfunc.mod b/src/xspice/icm/digital/d_srff/cfunc.mod new file mode 100644 index 000000000..2f3964fb9 --- /dev/null +++ b/src/xspice/icm/digital/d_srff/cfunc.mod @@ -0,0 +1,767 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_srff/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 24 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + 29 Jan 1992 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the d_srff code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + +/*============================================================================== + +FUNCTION cm_toggle_bit() + + +AUTHORS + + 27 Sept 1991 Jeffrey P. Murray + + +MODIFICATIONS + + NONE + + +SUMMARY + + Alters the state of a passed digital variable to its + complement. Thus, a ONE changes to a ZERO. A ZERO changes + to a ONE, and an UNKNOWN remains unchanged. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + No returned value. Passed pointer to variable is used + to redefine the variable value. + + +GLOBAL VARIABLES + + NONE + + +NON-STANDARD FEATURES + + NONE + +/*=============================================================================*/ + +/*=== CM_TOGGLE_BIT ROUTINE ===*/ + +static void cm_toggle_bit(Digital_State_t *bit) + +{ + /* Toggle bit from ONE to ZERO or vice versa, unless the + bit value is UNKNOWN. In the latter case, return + without changing the bit value. */ + + if ( UNKNOWN != *bit ) { + if ( ONE == *bit ) { + *bit = ZERO; + } + else { + *bit = ONE; + } + } + +} + + + +/*============================================================================== + +FUNCTION cm_eval_sr_result + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + Evaluates the S and R input states, plus the last state of + the flip flop, and returns the expected output value. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + +RETURNED VALUE + + A Digital_State_t. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_EVAL_SR_RESULT ROUTINE ===*/ + +static Digital_State_t cm_eval_sr_result(Digital_State_t s_input, + Digital_State_t r_input, + Digital_State_t old_output) +{ + Digital_State_t output; + + + switch (s_input) { + + case ZERO: + switch (r_input) { + case ZERO: + output = old_output; + break; + case ONE: + output = ZERO; + break; + case UNKNOWN: + output = UNKNOWN; + break; + } + break; + + case ONE: + switch (r_input) { + case ZERO: + output = ONE; + break; + case ONE: + output = UNKNOWN; + break; + case UNKNOWN: + output = UNKNOWN; + break; + } + break; + + + case UNKNOWN: + output = UNKNOWN; + break; + } + + return output; + +} + + + +/*============================================================================== + +FUNCTION cm_d_srff() + +AUTHORS + + 24 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 24 Sep 1991 Jeffrey P. Murray + 29 Jan 1992 Jeffrey P. Murray + +SUMMARY + + This function implements the d_srff code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_SRFF ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital sr-type flip flop for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/24/91 J.P.Murray * +************************************************/ + + +void cm_d_srff(ARGS) + +{ + int i; /* generic loop counter index */ + + + Digital_State_t *clk, /* current clk value */ + *clk_old, /* previous clk value */ + *set, /* current set value for dff */ + *set_old, /* previous set value for dff */ + *reset, /* current reset value for dff */ + *reset_old, /* previous reset value for dff */ + *out, /* current output for dff */ + *out_old, /* previous output for dff */ + + s_input, /* current j input value */ + r_input, /* current k input value */ + + temp; /* temp storage for state values */ + + + + /*** Setup required state variables ***/ + + if(INIT) { /* initial pass */ + + /* allocate storage */ + clk = clk_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + set = set_old = (Digital_State_t *) cm_event_alloc(1,sizeof(Digital_State_t)); + reset = reset_old = (Digital_State_t *) cm_event_alloc(2,sizeof(Digital_State_t)); + out = out_old = (Digital_State_t *) cm_event_alloc(3,sizeof(Digital_State_t)); + + /* declare load values */ + LOAD(s) = PARAM(sr_load); + LOAD(r) = PARAM(sr_load); + LOAD(clk) = PARAM(clk_load); + if ( !PORT_NULL(set) ) { + LOAD(set) = PARAM(set_load); + } + if ( !PORT_NULL(reset) ) { + LOAD(reset) = PARAM(reset_load); + } + + } + else { /* Retrieve previous values */ + + /* retrieve storage for the outputs */ + clk = (Digital_State_t *) cm_event_get_ptr(0,0); + clk_old = (Digital_State_t *) cm_event_get_ptr(0,1); + set = (Digital_State_t *) cm_event_get_ptr(1,0); + set_old = (Digital_State_t *) cm_event_get_ptr(1,1); + reset = (Digital_State_t *) cm_event_get_ptr(2,0); + reset_old = (Digital_State_t *) cm_event_get_ptr(2,1); + out = (Digital_State_t *) cm_event_get_ptr(3,0); + out_old = (Digital_State_t *) cm_event_get_ptr(3,1); + } + + + /******** load current input values if set or reset + are not connected, set to zero... ********/ + *clk = INPUT_STATE(clk); + if ( PORT_NULL(set) ) { + *set = *set_old = ZERO; + } + else { + *set = INPUT_STATE(set); + } + if ( PORT_NULL(reset) ) { + *reset = *reset_old = ZERO; + } + else { + *reset = INPUT_STATE(reset); + } + + + + /******* Determine analysis type and output appropriate values *******/ + + if (0.0 == TIME) { /****** DC analysis...output w/o delays ******/ + + temp = PARAM(ic); + + /** Modify output if set or reset lines are active **/ + if ( (*set==ONE) && (*reset==ZERO) ) temp = ONE; + if ( (*set==ZERO) && (*reset==ONE) ) temp = ZERO; + if ( (*set==ONE) && (*reset==ONE) ) temp = UNKNOWN; + + *out = *out_old = temp; + + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + } + + cm_toggle_bit(&temp); + + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = temp; + } + + } + + else { /****** Transient Analysis ******/ + + + + /***** Find input that has changed... *****/ + + /**** Test set value for change ****/ + if ( *set != *set_old ) { /* either set or set release */ + switch ( *set ) { + + case ONE: + if ( ONE != *reset) { + if (*out_old != ONE) { /* set will change output */ + /* output goes to ONE */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already set */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != UNKNOWN) { /* set will change output */ + /* output goes to UNKNOWN */ + *out = UNKNOWN; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = UNKNOWN; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = UNKNOWN; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case ZERO: + if ( ONE != *reset) { + /* output remains at current value */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + else { + if (*out_old != ZERO) { /* set will change output */ + /* output returns to reset condition */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case UNKNOWN: + + if ( ONE == *reset ) { + /* output goes to ZERO */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + } + } + else { + + /**** Test reset value for change ****/ + if ( *reset != *reset_old ) { /* either reset or reset release */ + switch ( *reset ) { + + case ONE: + if ( ONE != *set) { + if (*out_old != ZERO) { /* reset will change output */ + /* output goes to ZERO */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != UNKNOWN) { /* reset will change output */ + /* output goes to UNKNOWN */ + *out = UNKNOWN; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = UNKNOWN; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = UNKNOWN; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case ZERO: + if ( ONE != *set) { + /* output remains at current value */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + else { + if (*out_old != ONE) { /* reset will change output */ + /* output returns to set condition */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case UNKNOWN: + + if ( ONE == *set ) { + /* output goes to ONE */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + } + } + else { + + /**** Test clk value for change ****/ + if ( (*clk != *clk_old) && (*reset != ONE) && + (*set != ONE) ) { /* clock or clock release */ + switch ( *clk ) { + + case ONE: + /* active edge...calculate new data output */ + s_input = INPUT_STATE(s); + r_input = INPUT_STATE(r); + temp = cm_eval_sr_result(s_input,r_input,*out_old); + + + if (*out_old != temp) { /* clk will change output */ + + *out = temp; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + OUTPUT_DELAY(out) = PARAM(clk_delay); + } + + cm_toggle_bit(&temp); + + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = temp; + OUTPUT_DELAY(Nout) = PARAM(clk_delay); + } + } + else { + *out = *out_old; /* output same as before */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + + case ZERO: + case UNKNOWN: + /* inactive edge...return previous values */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + break; + + } + } + + else { /* data value must have changed... + return previous output value. */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + } + + + /***** Add additional rise or fall delays, if appropriate *****/ + + if ( *out != *out_old ) { /*** output value is changing ***/ + + switch ( *out ) { + + /** fall to zero value **/ + case 0: + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(fall_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(rise_delay); + } + break; + + /** rise to one value **/ + case 1: + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(rise_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(fall_delay); + } + break; + + /** unknown output **/ + default: + /* based on old value, add rise or fall delay */ + if (0 == *out_old) { /* add rising delay */ + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(rise_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(fall_delay); + } + } + else { /* add falling delay */ + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(fall_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(rise_delay); + } + } + break; + } + } + } + + /*** output strength values ***/ + if ( !PORT_NULL(out) ) { + OUTPUT_STRENGTH(out) = STRONG; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STRENGTH(Nout) = STRONG; + } +} + + + + + diff --git a/src/xspice/icm/digital/d_srff/ifspec.ifs b/src/xspice/icm/digital/d_srff/ifspec.ifs new file mode 100644 index 000000000..24fa51c17 --- /dev/null +++ b/src/xspice/icm/digital/d_srff/ifspec.ifs @@ -0,0 +1,135 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_srff code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_d_srff +Spice_Model_Name: d_srff +Description: "digital set-reset flip flop" + + +PORT_TABLE: + +Port_Name: s r +Description: "s input" "r input" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PORT_TABLE: + +Port_Name: clk +Description: "clock" +Direction: in +Default_Type: d +Allowed_Types: [d] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PORT_TABLE: + +Port_Name: set reset +Description: "asynch. set" "asynch. reset" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PORT_TABLE: + +Port_Name: out Nout +Description: "data output" "inverted data output" +Direction: out out +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: clk_delay set_delay +Description: "delay from clk" "delay from set" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: reset_delay ic +Description: "delay from reset" "output initial state" +Data_Type: real int +Default_Value: 1.0e-9 0 +Limits: [1e-12 -] [0 2] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "rise delay" "fall delay" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: sr_load clk_load +Description: "s,r load values (F)" "clk load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: set_load reset_load +Description: "set load value (F)" "reset load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + diff --git a/src/xspice/icm/digital/d_srlatch/cfunc.mod b/src/xspice/icm/digital/d_srlatch/cfunc.mod new file mode 100644 index 000000000..78afe381b --- /dev/null +++ b/src/xspice/icm/digital/d_srlatch/cfunc.mod @@ -0,0 +1,827 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE /cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 25 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 13 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + 29 Jan 1992 Jeffrey P. Murray + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + +/*============================================================================== + +FUNCTION cm_toggle_bit() + + +AUTHORS + + 27 Sept 1991 Jeffrey P. Murray + + +MODIFICATIONS + + NONE + + +SUMMARY + + Alters the state of a passed digital variable to its + complement. Thus, a ONE changes to a ZERO. A ZERO changes + to a ONE, and an UNKNOWN remains unchanged. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + No returned value. Passed pointer to variable is used + to redefine the variable value. + + +GLOBAL VARIABLES + + NONE + + +NON-STANDARD FEATURES + + NONE + + +===============================================================================*/ + +/*=== CM_TOGGLE_BIT ROUTINE ===*/ + +static void cm_toggle_bit(Digital_State_t *bit) + +{ + /* Toggle bit from ONE to ZERO or vice versa, unless the + bit value is UNKNOWN. In the latter case, return + without changing the bit value. */ + + if ( UNKNOWN != *bit ) { + if ( ONE == *bit ) { + *bit = ZERO; + } + else { + *bit = ONE; + } + } + +} + + + +/*============================================================================== + +FUNCTION cm_eval_sr_result + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + +MODIFICATIONS + + NONE + +SUMMARY + + Evaluates the S and R input states, plus the last state of + the latch, and returns the expected output value. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + +RETURNED VALUE + + A Digital_State_t. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_EVAL_SR_RESULT ROUTINE ===*/ + +static Digital_State_t cm_eval_sr_result(Digital_State_t s_input, + Digital_State_t r_input, + Digital_State_t old_output) +{ + Digital_State_t output; + + + switch (s_input) { + + case ZERO: + switch (r_input) { + case ZERO: + output = old_output; + break; + case ONE: + output = ZERO; + break; + case UNKNOWN: + output = UNKNOWN; + break; + } + break; + + case ONE: + switch (r_input) { + case ZERO: + output = ONE; + break; + case ONE: + output = UNKNOWN; + break; + case UNKNOWN: + output = UNKNOWN; + break; + } + break; + + + case UNKNOWN: + output = UNKNOWN; + break; + } + + return output; + +} + + + +/*============================================================================== + +FUNCTION cm_d_srlatch() + +AUTHORS + + 25 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 13 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + 29 Jan 1992 Jeffrey P. Murray + +SUMMARY + + This function implements the d_srlatch code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_SRLATCH ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital sr-type latch for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/25/91 J.P.Murray * +************************************************/ + + +void cm_d_srlatch(ARGS) + +{ + int i; /* generic loop counter index */ + + + Digital_State_t *s, /* current s-input value */ + *s_old, /* previous s-input value */ + *r, /* current r-input value */ + *r_old, /* previous r-input value */ + *enable, /* current enable value */ + *enable_old, /* previous enable value */ + *set, /* current set value for srlatch */ + *set_old, /* previous set value for srlatch */ + *reset, /* current reset value for srlatch */ + *reset_old, /* previous reset value for srlatch */ + *out, /* current output for srlatch */ + *out_old, /* previous output for srlatch */ + + temp; /* temp storage for state values */ + + + + /*** Setup required state variables ***/ + + if(INIT) { /* initial pass */ + + /* allocate storage */ + s = s_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + r = r_old = (Digital_State_t *) cm_event_alloc(1,sizeof(Digital_State_t)); + enable = enable_old = (Digital_State_t *) cm_event_alloc(2,sizeof(Digital_State_t)); + set = set_old = (Digital_State_t *) cm_event_alloc(3,sizeof(Digital_State_t)); + reset = reset_old = (Digital_State_t *) cm_event_alloc(4,sizeof(Digital_State_t)); + out = out_old = (Digital_State_t *) cm_event_alloc(5,sizeof(Digital_State_t)); + + /* declare load values */ + LOAD(s) = PARAM(sr_load); + LOAD(r) = PARAM(sr_load); + LOAD(enable) = PARAM(enable_load); + if ( !PORT_NULL(set) ) { + LOAD(set) = PARAM(set_load); + } + if ( !PORT_NULL(reset) ) { + LOAD(reset) = PARAM(reset_load); + } + + } + else { /* Retrieve previous values */ + + /* retrieve storage for the outputs */ + s = (Digital_State_t *) cm_event_get_ptr(0,0); + s_old = (Digital_State_t *) cm_event_get_ptr(0,1); + r = (Digital_State_t *) cm_event_get_ptr(1,0); + r_old = (Digital_State_t *) cm_event_get_ptr(1,1); + enable = (Digital_State_t *) cm_event_get_ptr(2,0); + enable_old = (Digital_State_t *) cm_event_get_ptr(2,1); + set = (Digital_State_t *) cm_event_get_ptr(3,0); + set_old = (Digital_State_t *) cm_event_get_ptr(3,1); + reset = (Digital_State_t *) cm_event_get_ptr(4,0); + reset_old = (Digital_State_t *) cm_event_get_ptr(4,1); + out = (Digital_State_t *) cm_event_get_ptr(5,0); + out_old = (Digital_State_t *) cm_event_get_ptr(5,1); + } + + + + /******* load current input values if set or reset + are not connected, set to zero... *******/ + *s = INPUT_STATE(s); + *r = INPUT_STATE(r); + *enable = INPUT_STATE(enable); + if ( PORT_NULL(set) ) { + *set = *set_old = ZERO; + } + else { + *set = INPUT_STATE(set); + } + if ( PORT_NULL(reset) ) { + *reset = *reset_old = ZERO; + } + else { + *reset = INPUT_STATE(reset); + } + + + + + /******* Determine analysis type and output appropriate values *******/ + + if (0.0 == TIME) { /****** DC analysis...output w/o delays ******/ + + temp = PARAM(ic); + + /** Modify output if set or reset lines are active **/ + if ( (*enable==ONE) && (*s==ONE) && (*r==ZERO) ) temp = ONE; + if ( (*enable==ONE) && (*s==ZERO) && (*r==ONE) ) temp = ZERO; + if ( (*set==ONE) && (*reset==ZERO) ) temp = ONE; + if ( (*set==ZERO) && (*reset==ONE) ) temp = ZERO; + if ( (*set==ONE) && (*reset==ONE) ) temp = UNKNOWN; + + *out = *out_old = temp; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + } + if ( !PORT_NULL(Nout) ) { + cm_toggle_bit(&temp); + OUTPUT_STATE(Nout) = temp; + } + } + + else { /****** Transient Analysis ******/ + + + /***** Find input that has changed... *****/ + + /**** Test set value for change ****/ + if ( *set != *set_old ) { /* either set or set release */ + switch ( *set ) { + + case ONE: + if ( ONE != *reset) { + if (*out_old != ONE) { /* set will change output */ + *out = ONE; + + /* output goes to ONE */ + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already set */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != UNKNOWN) { /* set will change output */ + *out = UNKNOWN; + + /* output goes to UNKNOWN */ + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = UNKNOWN; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = UNKNOWN; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case ZERO: + case UNKNOWN: + if ( ONE != *reset) { + if ( ONE == *enable ) { + /* active level...save & output current value */ + temp = cm_eval_sr_result(*s,*r,*out_old); + + if (*out_old != temp) { /* enable will change output */ + *out = temp; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + cm_toggle_bit(&temp); + OUTPUT_STATE(Nout) = temp; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output same as before */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + /* output remains at current value */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != ZERO) { /* set will change output */ + /* output returns to reset condition */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + } + } + else { + + /**** Test reset value for change ****/ + if ( *reset != *reset_old ) { /* either reset or reset release */ + switch ( *reset ) { + + case ONE: + if ( ONE != *set) { + if (*out_old != ZERO) { /* reset will change output */ + /* output goes to ZERO */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != UNKNOWN) { /* reset will change output */ + /* output goes to UNKNOWN */ + *out = UNKNOWN; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = UNKNOWN; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = UNKNOWN; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case ZERO: + case UNKNOWN: + if ( ONE != *set) { + if ( ONE == *enable ) { + /* active level...save & output current value */ + temp = cm_eval_sr_result(*s,*r,*out_old); + + if (*out_old != temp) { /* enable will change output */ + *out = temp; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + cm_toggle_bit(&temp); + OUTPUT_STATE(Nout) = temp; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output same as before */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + /* output remains at current value */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != ONE) { /* reset will change output */ + /* output returns to set condition */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + } + } + else { + + /**** Test for enable change... ****/ + if ( (*enable != *enable_old) && (*reset != ONE) && + (*set != ONE) ) { /* enable or enable release */ + switch ( *enable ) { + + case ONE: + /* active edge...save & output current data value */ + temp = cm_eval_sr_result(*s,*r,*out_old); + + if (*out_old != temp) { /* enable will change output */ + *out = temp; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + OUTPUT_DELAY(out) = PARAM(enable_delay); + } + if ( !PORT_NULL(Nout) ) { + cm_toggle_bit(&temp); + OUTPUT_STATE(Nout) = temp; + OUTPUT_DELAY(Nout) = PARAM(enable_delay); + } + } + else { + *out = *out_old; /* output same as before */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + + case ZERO: + case UNKNOWN: + /* inactive edge...return previous values */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + break; + } + } + + else { /* test data value for change... */ + + if ( ((*s != *s_old) || (*r != *r_old)) && + (*reset != ONE) && (*set != ONE) ) { + /* input values have changed... + test enable, and if active, update + the output...else return w/o change. */ + switch ( *enable ) { + + case ONE: + /* active level...save & output current data value */ + temp = cm_eval_sr_result(*s,*r,*out_old); + + if (*out_old != temp) { /* enable will change output */ + *out = temp; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + OUTPUT_DELAY(out) = PARAM(sr_delay); + } + if ( !PORT_NULL(Nout) ) { + cm_toggle_bit(&temp); + OUTPUT_STATE(Nout) = temp; + OUTPUT_DELAY(Nout) = PARAM(sr_delay); + } + } + else { + *out = *out_old; /* output same as before */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + + case ZERO: + case UNKNOWN: + /* inactive level...return previous values */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + break; + } + } + else { /* nothing has changed!!! This shouldn't happen! */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + } + } + + /***** Add additional rise or fall delays, if appropriate *****/ + + if ( *out != *out_old ) { /*** output value is changing ***/ + + switch ( *out ) { + + /** fall to zero value **/ + case 0: + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(fall_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(rise_delay); + } + break; + + /** rise to one value **/ + case 1: + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(rise_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(fall_delay); + } + break; + + /** unknown output **/ + default: + /* based on old value, add rise or fall delay */ + if (0 == *out_old) { /* add rising delay */ + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(rise_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(fall_delay); + } + } + else { /* add falling delay */ + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(fall_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(rise_delay); + } + } + break; + } + } + } + + /*** output strength values ***/ + if ( !PORT_NULL(out) ) { + OUTPUT_STRENGTH(out) = STRONG; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STRENGTH(Nout) = STRONG; + } +} + + + + + diff --git a/src/xspice/icm/digital/d_srlatch/ifspec.ifs b/src/xspice/icm/digital/d_srlatch/ifspec.ifs new file mode 100644 index 000000000..4b19a3de9 --- /dev/null +++ b/src/xspice/icm/digital/d_srlatch/ifspec.ifs @@ -0,0 +1,147 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_srlatch code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_d_srlatch +Spice_Model_Name: d_srlatch +Description: "digital sr-type latch" + + +PORT_TABLE: + +Port_Name: s r +Description: "s input" "r input" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PORT_TABLE: + +Port_Name: enable +Description: "enable" +Direction: in +Default_Type: d +Allowed_Types: [d] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PORT_TABLE: + +Port_Name: set reset +Description: "asynch. set" "asynch. reset" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PORT_TABLE: + +Port_Name: out Nout +Description: "data output" "inverted data output" +Direction: out out +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: sr_delay +Description: "delay from s or r input change" +Data_Type: real +Default_Value: 1.0e-9 +Limits: [1e-12 -] +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: enable_delay set_delay +Description: "delay from clk" "delay from set" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: reset_delay ic +Description: "delay from reset" "output initial state" +Data_Type: real int +Default_Value: 1.0e-9 0 +Limits: [1e-12 -] [0 2] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "rise delay" "fall delay" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: sr_load enable_load +Description: "s & r load values (F)" "clk load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: set_load reset_load +Description: "set load value (F)" "reset load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + diff --git a/src/xspice/icm/digital/d_state/cfunc.mod b/src/xspice/icm/digital/d_state/cfunc.mod new file mode 100644 index 000000000..b31718c45 --- /dev/null +++ b/src/xspice/icm/digital/d_state/cfunc.mod @@ -0,0 +1,2217 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_state/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 June 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include +#include +#include +#include + + + +/*=== CONSTANTS ========================*/ + +#define MAX_STRING_SIZE 200 + +#define HEADER 1 +#define CONTINUATION 2 + +#define OK 0 +#define FAIL 1 + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + +typedef struct { + int current_state, /* current state of the machine (similar to + current state of the union, current state + of the economy, etc. etc. 8-) */ + index0, /* actual word number (0 to depth-1) in which the + first line of the current_state definition + may be found. */ + indexN, /* word number (0 to depth-1) of the final curren_state + definition line...if a state is defined in only one + line, index0 and indexN will be equal. */ + num_outputs, /* width of bits[] table...equal to size of + out port */ + num_inputs, /* width of inputs[] table...equal to size of + in port */ + depth, /* depth of table...equal to size of + current_state & next_state arrays, + and to the total number of vectors + retrieved from the + state.in file. */ + *state, /* integer array holding the state + index values...note that each state will + have at least one and as many as 2^N + "words" assigned to it, where N = number + of input lines to the state machine. */ + *next_state; /* integer array holding the next state + to jump to given the input values + held by the inputs[] array...note that each + state will have at least one and as many as 2^N + "words" assigned to it, where N = number + of input lines to the state machine. */ + + + short *bits, /* the storage array for the + output bit representations... + this will have size equal to + (width * depth)/4, since one + short will hold four 12-state + bit descriptions. */ + *inputs; /* the storage array for the + input bit representations... + this will have size equal to + (width * depth)/8, since one + short will hold eight 3-state + bit descriptions. */ +} State_Table_t; + + + + + + + + +/* Type definition for each possible token returned. */ +typedef enum token_type_s {CNV_NO_TOK,CNV_STRING_TOK} Cnv_Token_Type_t; + + + + + + +typedef char line_t[82]; /* A SPICE size line. <= 80 characters plus '\n\0' */ + + + + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + + + +/*============================================================================== + +FUNCTION *CNVgettok() + +AUTHORS + + 13 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 8 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function obtains the next token from an input stream. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + +RETURNED VALUE + + Returns a string value representing the next token. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + + +/*=== Static CNVgettok ROUTINE ================*/ +/* +Get the next token from the input string. The input string pointer +is advanced to the following token and the token from the input +string is copied to malloced storage and a pointer to that storage +is returned. The original input string is undisturbed. +*/ + +static char *CNVgettok(char **s) + +{ + + char *buf; /* temporary storage to copy token into */ + char *temp; /* temporary storage to copy token into */ + char *ret_str; /* storage for returned string */ + + int i; + + /* allocate space big enough for the whole string */ + + buf = (void *) malloc(strlen(*s) + 1); + + /* skip over any white space */ + + while(isspace(**s) || (**s == '=') || + (**s == '(') || (**s == ')') || (**s == ',')) + (*s)++; + + /* isolate the next token */ + + switch(**s) { + + case '\0': /* End of string found */ + free(buf); + return(NULL); + + + default: /* Otherwise, we are dealing with a */ + /* string representation of a number */ + /* or a mess o' characters. */ + i = 0; + while( (**s != '\0') && + (! ( isspace(**s) || (**s == '=') || + (**s == '(') || (**s == ')') || + (**s == ',') + ) ) ) { + buf[i] = **s; + i++; + (*s)++; + } + buf[i] = '\0'; + break; + } + + /* skip over white space up to next token */ + + while(isspace(**s) || (**s == '=') || + (**s == '(') || (**s == ')') || (**s == ',')) + (*s)++; + + /* make a copy using only the space needed by the string length */ + + + ret_str = (void *) malloc(strlen(buf) + 1); + ret_str = strcpy(ret_str,buf); + + free(buf); + + return(ret_str); +} + + +/*============================================================================== + +FUNCTION *CNVget_token() + +AUTHORS + + 13 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 8 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function obtains the next token from an input stream. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + +RETURNED VALUE + + Returns a string value representing the next token. Uses + *CNVget_tok. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CNVget_token ROUTINE =============*/ +/* +Get the next token from the input string together with its type. +The input string pointer +is advanced to the following token and the token from the input +string is copied to malloced storage and a pointer to that storage +is returned. The original input string is undisturbed. +*/ + +static char *CNVget_token(char **s, Cnv_Token_Type_t *type) + +{ + + char *ret_str; /* storage for returned string */ + + /* get the token from the input line */ + + ret_str = CNVgettok(s); + + + /* if no next token, return */ + + if(ret_str == NULL) { + *type = CNV_NO_TOK; + return(NULL); + } + + /* else, determine and return token type */ + + switch(*ret_str) { + + default: + *type = CNV_STRING_TOK; + break; + + } + + return(ret_str); +} + + + + +/*============================================================================== + +FUNCTION cnv_get_spice_value() + +AUTHORS + + ??? Bill Kuhn + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function takes as input a string token from a SPICE + deck and returns a floating point equivalent value. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + +RETURNED VALUE + + Returns the floating point value in pointer *p_value. Also + returns an integer representing successful completion. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CNV_get_spice_value ROUTINE =============*/ + +/* + Function takes as input a string token from a SPICE +deck and returns a floating point equivalent value. +*/ + + +static int cnv_get_spice_value(str,p_value) + +char *str; /* IN - The value text e.g. 1.2K */ +float *p_value; /* OUT - The numerical value */ +{ + + + /* the following were "int4" devices - jpm */ + int len; + int i; + int n_matched; + + line_t val_str; + + char *suffix; + char c; + char c1; + + float scale_factor; + float value; + + + /* Scan the input string looking for an alpha character that is not */ + /* 'e' or 'E'. Such a character is assumed to be an engineering */ + /* suffix as defined in the Spice 2G.6 user's manual. */ + + len = strlen(str); + if( len > (sizeof(val_str) - 1)) + len = sizeof(val_str) - 1; + + for(i = 0; i < len; i++) { + c = str[i]; + if( isalpha(c) && (c != 'E') && (c != 'e') ) + break; + else if( isspace(c) ) + break; + else + val_str[i] = c; + } + val_str[i] = '\0'; + + + /* Determine the scale factor */ + + if( (i >= len) || (! isalpha(c)) ) + scale_factor = 1.0; + else { + + if(islower(c)) + c = tolower(c); + + switch(c) { + + case 't': + scale_factor = 1.0e12; + break; + + case 'g': + scale_factor = 1.0e9; + break; + + case 'k': + scale_factor = 1.0e3; + break; + + case 'u': + scale_factor = 1.0e-6; + break; + + case 'n': + scale_factor = 1.0e-9; + break; + + case 'p': + scale_factor = 1.0e-12; + break; + + case 'f': + scale_factor = 1.0e-15; + break; + + case 'm': + i++; + if(i >= len) { + scale_factor = 1.0e-3; + break; + } + c1 = str[i]; + if(! isalpha(c1)) { + scale_factor = 1.0e-3; + break; + } + if(islower(c1)) + c1 = toupper(c1); + if(c1 == 'E') + scale_factor = 1.0e6; + else if(c1 == 'I') + scale_factor = 25.4e-6; + else + scale_factor = 1.0e-3; + break; + + default: + scale_factor = 1.0; + } + } + + /* Convert the numeric portion to a float and multiply by the */ + /* scale factor. */ + + n_matched = sscanf(val_str,"%e",&value); + + if(n_matched < 1) { + *p_value = 0.0; + return(FAIL); + } + + *p_value = value * scale_factor; + return(OK); +} + + +/*============================================================================== + +FUNCTION cm_inputs_mask_and_retrieve() + +AUTHORS + + 23 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + Masks off and retrieves a two-bit value from a short + integer word passed to the function, using an offset value. + This effectively handles retrieval of eight two-bit values + from a single short integer space in order to conserve memory. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns a Digital_t value. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_INPUTS_MASK_AND_RETRIEVE ROUTINE ===*/ + +/************************************************** +* The following routine masks and retrieves * +* the value passed to it by the out value * +* by masking the appropriate bits in the * +* base integer. The particular bit affected * +* is determined by the bit_offset value. * +* * +* Created 7/23/91 J.P.Murray * +**************************************************/ + +static void cm_inputs_mask_and_retrieve(short base,int bit_offset,Digital_t *out) +{ + + + short value; /* the hexadecimal value of the masked bit */ + + + + switch (bit_offset) { + case 0: + break; + + case 1: + base = base >> 2; + break; + + case 2: + base = base >> 4; + break; + + case 3: + base = base >> 6; + break; + + case 4: + base = base >> 8; + break; + + case 5: + base = base >> 10; + break; + + case 6: + base = base >> 12; + break; + + case 7: + base = base >> 14; + break; + } + + + value = 0x0003 & base; + + + switch (value) { + + case 0: out->state = ZERO; + break; + + case 1: out->state = ONE; + break; + + case 2: out->state = UNKNOWN; + break; + } + +} + + +/*============================================================================== + +FUNCTION cm_set_indices() + +AUTHORS + + 23 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine retrieves the current_state value + from the *states structure. It then searches the entire + state[] array to determine the index0 and indexN values + corresponding to the first and last entries in the + state[] array for the current state. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns a status int value. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_SET_INDICES ROUTINE ===*/ + +/************************************************ +* The following routine retrieves the * +* current_state value from the *states * +* structure. It then searches the entire * +* state[] array to determine the index0 and * +* indexN values corresponding to the first * +* and last entries in the state[] array for * +* the current state. * +* * +* Created 7/23/91 J.P. Murray * +************************************************/ + + +static int cm_set_indices(State_Table_t *states) +{ + int i, /* indexing variable */ + index0_set, /* flag for index0 */ + indexN_set; /* flag for index1 */ + + + states->index0 = 0; + states->indexN = 0; + index0_set = 0; + indexN_set = 0; + + + for (i=0; i< states->depth; i++) { /* loop through all states */ + + if ( states->state[i] == states->current_state ) { + /* states match... */ + + /* if not already set, set index0... */ + if ( 0 == index0_set ) { + states->index0 = i; + states->indexN = i; + index0_set = 1; + } + + if ( 1 < (i - states->indexN) ) { + /* ERROR!! This means that a state match was + found in a nonn-contiguous portion of the + state.in file...this is not allowed! */ + return TRUE; + } + else { + /* update indexN. */ + states->indexN = i; + } + } + } + return FALSE; +} + + +/*============================================================================== + +FUNCTION cm_compare_to_inputs() + +AUTHORS + + 23 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine retrieves the + the inputs[] bit value pointed to by + the word_num and bit_num integers, compares + this value with the "in" state value, and + returns a "0" if they match, and a "1" if + they do not match. + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns a status int value. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_COMPARE_TO_INPUTS ROUTINE ===*/ + +/************************************************ +* The following routine retrieves the * +* the inputs[] bit value pointed to by * +* the word_num and bit_num integers, compares * +* this value with the "in" state value, and * +* returns a "0" if they match, and a "1" if * +* they do not match. * +* * +* Created 7/23/91 J.P.Murray * +************************************************/ + + +static int cm_compare_to_inputs(State_Table_t *states,int index,int bit_number, Digital_State_t in) +{ + int int1, /* temp storage variable */ + bit_index, /* bits base address at which word bits will + be found */ + bit_offset; /* offset from ram base address at which bit[0] + of the required word can be found */ + + short base; /* variable to hold current base integer for + comparison purposes. */ + + double double1, + double2; /* holding variables for modf routine */ + + Digital_t out; /* output variable for state retrieved */ + + + /* obtain offset value from index, word_width & bit_number */ + int1 = index * states->num_inputs + bit_number; + double1 = int1 / 8.0; + modf(double1, &double2); + bit_index = double2; + bit_offset = int1 - (double2 * 8.0); + + /* retrieve entire base_address bits integer... */ + base = states->inputs[bit_index]; + + /* for each offset, mask off the bits and determine values */ + + cm_inputs_mask_and_retrieve(base,bit_offset,&out); + + if ( out.state == in ) { /* bit matches */ + return 0; + } + else + if ( 2==out.state ) { /* bit compared to is a "don't care" */ + return 0; + } + else { /* no match */ + return 1; + } +} + + +/*============================================================================== + +FUNCTION cm_inputs_mask_and_store() + +AUTHORS + + 22 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine masks and stores + the value passed to it by the out value + by masking the appropriate bits in the + base integer. The particular bit affected + is determined by the bit_offset value. + This routine stores to the inputs[] array. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns a status int value. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_INPUTS_MASK_AND_STORE ROUTINE ===*/ + +/************************************************ +* The following routine masks and stores * +* the value passed to it by the out value * +* by masking the appropriate bits in the * +* base integer. The particular bit affected * +* is determined by the bit_offset value. * +* This routine stores to the inputs[] array. * +* * +* Created 7/22/91 * +* Last Modified 7/22/91 J.P.Murray * +************************************************/ + +static int cm_inputs_mask_and_store(short *base,int bit_offset,int bit_value) +{ + switch (bit_offset) { + case 0: + *base = *base & 0xfffc; + break; + + case 1: + *base = *base & 0xfff3; + bit_value = bit_value << 2; + break; + + case 2: + *base = *base & 0xffcf; + bit_value = bit_value << 4; + break; + + case 3: + *base = *base & 0xff3f; + bit_value = bit_value << 6; + break; + + case 4: + *base = *base & 0xfcff; + bit_value = bit_value << 8; + break; + + case 5: + *base = *base & 0xf3ff; + bit_value = bit_value << 10; + break; + + case 6: + *base = *base & 0xcfff; + bit_value = bit_value << 12; + break; + + case 7: + *base = *base & 0x3fff; + bit_value = bit_value << 14; + break; + } + + *base = *base | bit_value; +} + + + + +/*============================================================================== + +FUNCTION cm_store_inputs_value() + +AUTHORS + + 23 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine retrieves four-bit + data from short integer array "bits". The + integers are assumed to be at least two + bytes each, so each will hold four four- + bit values. + + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + NONE + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_STORE_INPUTS_VALUE ROUTINE ===*/ + +/************************************************ +* The following routine retrieves four-bit * +* data from short integer array "bits". The * +* integers are assumed to be at least two * +* bytes each, so each will hold four four- * +* bit values. * +* * +* Created 7/23/91 J.P.Murray * +************************************************/ + +static void cm_store_inputs_value(State_Table_t *states,int index, int bit_number, + int in_val) + +{ + int err, /* error index value */ + int1, /* temp storage variable */ + bit_index, /* bits base address at which word bits will + be found */ + bit_offset; /* offset from ram base address at which bit[0] + of the required word can be found */ + + short base; /* variable to hold current base integer for + comparison purposes. */ + + double double1, + double2; /* holding variables for modf routine */ + + + + /* obtain offset value from word_number, word_width & + bit_number */ + int1 = index * states->num_inputs + bit_number; + double1 = int1 / 8.0; + modf(double1, &double2); + bit_index = double2; + bit_offset = int1 - (double2 * 8.0); + + /* retrieve entire base_address bits integer... */ + base = states->inputs[bit_index]; + + /* for each offset, mask off the bits and store values */ + cm_inputs_mask_and_store(&base,bit_offset,in_val); + + /* store modified base value */ + states->inputs[bit_index] = base; +} + + +/*============================================================================== + +FUNCTION cm_bits_mask_and_store() + +AUTHORS + + 22 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine masks and stores + the value passed to it by the out value + by masking the appropriate bits in the + base integer. The particular bit affected + is determined by the bit_offset value. + This routine stores to the bits[] array. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns a status integer. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + + +/*=== Static CM_BITS_MASK_AND_STORE ROUTINE ===*/ + +/************************************************ +* The following routine masks and stores * +* the value passed to it by the out value * +* by masking the appropriate bits in the * +* base integer. The particular bit affected * +* is determined by the bit_offset value. * +* This routine stores to the bits[] array. * +* * +* Created 7/22/91 * +* Last Modified 7/22/91 J.P.Murray * +************************************************/ + +static int cm_bits_mask_and_store(short *base,int bit_offset,int bit_value) +{ + switch (bit_offset) { + case 0: + *base = *base & 0xfff0; + break; + + case 1: + *base = *base & 0xff0f; + bit_value = bit_value << 4; + break; + + case 2: + *base = *base & 0xf0ff; + bit_value = bit_value << 8; + break; + + case 3: + *base = *base & 0x0fff; + bit_value = bit_value << 12; + break; + } + + *base = *base | bit_value; +} + + + + +/*============================================================================== + +FUNCTION cm_bits_mask_and_retrieve() + +AUTHORS + + 22 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine masks and retrieves + the value passed to it by the out value + by masking the appropriate bits in the + base integer. The particular bit affected + is determined by the bit_offset value. + + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + NONE + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_BITS_MASK_AND_RETRIEVE ROUTINE ===*/ + +/************************************************** +* The following routine masks and retrieves * +* the value passed to it by the out value * +* by masking the appropriate bits in the * +* base integer. The particular bit affected * +* is determined by the ram_offset value. * +* * +* Created 7/22/91 * +* Last Modified 7/22/91 J.P.Murray * +**************************************************/ + +static void cm_bits_mask_and_retrieve(short base,int bit_offset,Digital_t *out) +{ + + + short value; /* the hexadecimal value of the masked bit */ + + + + switch (bit_offset) { + case 0: + break; + + case 1: + base = base >> 4; + break; + + case 2: + base = base >> 8; + break; + + case 3: + base = base >> 12; + break; + } + + + value = 0x000f & base; + + + switch (value) { + + case 0: out->state = ZERO; + out->strength = STRONG; + break; + + case 1: out->state = ONE; + out->strength = STRONG; + break; + + case 2: out->state = UNKNOWN; + out->strength = STRONG; + break; + + case 3: out->state = ZERO; + out->strength = RESISTIVE; + break; + + case 4: out->state = ONE; + out->strength = RESISTIVE; + break; + + case 5: out->state = UNKNOWN; + out->strength = RESISTIVE; + break; + + case 6: out->state = ZERO; + out->strength = HI_IMPEDANCE; + break; + + case 7: out->state = ONE; + out->strength = HI_IMPEDANCE; + break; + + case 8: out->state = UNKNOWN; + out->strength = HI_IMPEDANCE; + break; + + case 9: out->state = ZERO; + out->strength = UNDETERMINED; + break; + + case 10: out->state = ONE; + out->strength = UNDETERMINED; + break; + + case 11: out->state = UNKNOWN; + out->strength = UNDETERMINED; + break; + } +} + + +/*============================================================================== + +FUNCTION cm_get_bits_value() + +AUTHORS + + 22 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 23 Jul 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine retrieves four-bit + data from short integer array "bits". The + integers are assumed to be at least two + bytes each, so each will hold four four- + bit values. + + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + NONE + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_GET_BITS_VALUE ROUTINE ===*/ + +/************************************************ +* The following routine retrieves four-bit * +* data from short integer array "bits". The * +* integers are assumed to be at least two * +* bytes each, so each will hold four four- * +* bit values. * +* * +* Created 7/22/91 * +* Last Modified 7/23/91 J.P.Murray * +************************************************/ + +static void cm_get_bits_value(State_Table_t *states,int index, int bit_number, + Digital_t *out) + +{ + int err, /* error index value */ + int1, /* temp storage variable */ + bit_index, /* bits base address at which word bits will + be found */ + bit_offset; /* offset from ram base address at which bit[0] + of the required word can be found */ + + short base; /* variable to hold current base integer for + comparison purposes. */ + + double double1, + double2; /* holding variables for modf routine */ + + + + /* obtain offset value from index, word_width & bit_number */ + int1 = index * states->num_outputs + bit_number; + double1 = int1 / 4.0; + modf(double1, &double2); + bit_index = double2; + bit_offset = int1 - (double2 * 4.0); + + /* retrieve entire base_address bits integer... */ + base = states->bits[bit_index]; + + /* for each offset, mask off the bits and determine values */ + + cm_bits_mask_and_retrieve(base,bit_offset,out); + +} + + + +/*============================================================================== + +FUNCTION cm_store_bits_value() + +AUTHORS + + 23 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine retrieves four-bit + data from short integer array "bits". The + integers are assumed to be at least two + bytes each, so each will hold four four- + bit values. + + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + NONE + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_STORE_BITS_VALUE ROUTINE ===*/ + +/************************************************ +* The following routine retrieves four-bit * +* data from short integer array "bits". The * +* integers are assumed to be at least two * +* bytes each, so each will hold four four- * +* bit values. * +* * +* Created 7/23/91 * +* Last Modified 7/23/91 J.P.Murray * +************************************************/ + +static void cm_store_bits_value(State_Table_t *states,int index, int bit_number, + int in_val) + +{ + int err, /* error index value */ + int1, /* temp storage variable */ + bit_index, /* bits base address at which word bits will + be found */ + bit_offset; /* offset from ram base address at which bit[0] + of the required word can be found */ + + short base; /* variable to hold current base integer for + comparison purposes. */ + + double double1, + double2; /* holding variables for modf routine */ + + + + /* obtain offset value from word_number, word_width & + bit_number */ + int1 = index * states->num_outputs + bit_number; + double1 = int1 / 4.0; + modf(double1, &double2); + bit_index = double2; + bit_offset = int1 - (double2 * 4.0); + + /* retrieve entire base_address bits integer... */ + base = states->bits[bit_index]; + + /* for each offset, mask off the bits and store values */ + cm_bits_mask_and_store(&base,bit_offset,in_val); + + /* store modified base value */ + states->bits[bit_index] = base; +} + + + +/*============================================================================== + +FUNCTION cm_read_state_file() + +AUTHORS + + 15 Jul 1991 Jeffrey P. Murray + +MODIFICATIONS + + 23 Jul 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + The following routine reads the file + *state_file, parses the file, and stores + the values found there into the *state, + *bits, *inputs and *next_state arrays. + + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + Returns a status integer value. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== Static CM_READ_STATE_FILE ROUTINE ===*/ + + +/************************************************** +* The following routine reads the file * +* *state_file, parses the file, and stores * +* the values found there into the *state, * +* *bits, *inputs and *next_state arrays. * +* * +* Created 7/15/91 * +* Last Modified 7/23/91 J.P.Murray * +**************************************************/ + +static int cm_read_state_file(FILE *state_file,State_Table_t *states) +{ + int i, /* indexing variable */ + j, /* indexing variable */ + num_tokens, /* number of tokens in a given string */ + bit_index, /* index to which bits[] integer we are accessing */ + bit_offset, /* index to which bit within the current bits[] + integer we are accessing */ + string_type, /* integer holding value corresponding to the + type of input string obtained: + 1 = HEADER => State Header string + 2 = CONTINUATION => a continuation line... + values of state and + bits must be retreived from + the previous string. */ + int1; /* temporary holding variable */ + + + Cnv_Token_Type_t type; /* variable for testing token type returned. */ + + + char temp[MAX_STRING_SIZE], /* holding string variable for testing + input from state.in */ + *s, /* main string variable */ + *base_address, /* storage location for base address + of string. */ + *token; /* a particular token from the string */ + + + float number; /* holding variable for timepoint values */ + + double double1, /* temporary holding variable */ + double2; /* temporary holding variable */ + + short bit_value, /* holding variable for value read from + state.in file which needs to be stored */ + base; /* holding variable for existing + non-masked bits[] integer */ + + + i = 0; + s = temp; + while ( fgets(s,MAX_STRING_SIZE,state_file) != NULL) { + /* Test this string to see if it is whitespace... */ + + base_address = s; + while(isspace(*s) || (*s == '*')) + (s)++; + if ( *s != '\0' ) { /* This is not a blank line, so process... */ + s = base_address; + + if ( '*' != s[0] ) { + + /* Count up total number of tokens including \0... */ + j = 0; + type = CNV_STRING_TOK; + while ( type != CNV_NO_TOK ) { + token = CNVget_token(&s, &type); + j++; + } + num_tokens = (j-1); + + /* Test the type of entry this number of + tokens represents. Valid types are: + + a. State Header with state, bits, inputs + and next_state entries...total tokens + equals num_inputs + num_outputs + 3 + (e.g. "5 0s 0s 0s 0 0 -> 6"). + + b. State continuation line with inputs + and next_state only...total tokens + equals num_inputs + 2. + (e.g. " 0 1 -> 7"). + */ + + if ( (3 + states->num_inputs + states->num_outputs) == + num_tokens) { + string_type = HEADER; + } + else { + if ( (2 + states->num_inputs) == num_tokens) { + string_type = CONTINUATION; + } + else { /* Number of tokens is incorrect */ + return 1; + } + } + + /* reset s to beginning... */ + s = base_address; + + /** Retrieve each token, analyze, and **/ + /** store the state, bits, inputs & **/ + /** next_state information. **/ + + if ( HEADER == string_type ) { /**** header type loop ****/ + + for (j=0; j<(states->num_inputs + states->num_outputs + + 3); j++) { + + token = CNVget_token(&s, &type); + + + if ( 0 == j ) { /* obtain state value... */ + + /* convert to a floating point number... */ + cnv_get_spice_value(token,&number); + + states->state[i] = number; + + + } + else { /* obtain each bit value & set bits entry */ + + if ( states->num_outputs >= j ) { + + /* preset this bit location */ + bit_value = 12; + + if (0 == strcmp(token,"0s")) bit_value = 0; + if (0 == strcmp(token,"1s")) bit_value = 1; + if (0 == strcmp(token,"Us")) bit_value = 2; + if (0 == strcmp(token,"0r")) bit_value = 3; + if (0 == strcmp(token,"1r")) bit_value = 4; + if (0 == strcmp(token,"Ur")) bit_value = 5; + if (0 == strcmp(token,"0z")) bit_value = 6; + if (0 == strcmp(token,"1z")) bit_value = 7; + if (0 == strcmp(token,"Uz")) bit_value = 8; + if (0 == strcmp(token,"0u")) bit_value = 9; + if (0 == strcmp(token,"1u")) bit_value = 10; + if (0 == strcmp(token,"Uu")) bit_value = 11; + + /* if this bit was not recognized, return with an error */ + if (12 == bit_value) { + return 1; + } + else { /* need to store this value in the bits[] array */ + + cm_store_bits_value(states,i,(j-1),bit_value); + + + } + } + else { /* obtain inputs info... */ + + if ( (states->num_outputs + states->num_inputs) + >= j ) { + + /* preset this bit location */ + bit_value = 3; + + if (0 == strcmp(token,"0")) bit_value = 0; + if (0 == strcmp(token,"1")) bit_value = 1; + if (0 == strcmp(token,"x")) bit_value = 2; + if (0 == strcmp(token,"X")) bit_value = 2; + + /* if this bit was not recognized, return with an error */ + if (3 == bit_value) { + return 1; + } + else { /* need to store this value in the inputs[] array */ + + cm_store_inputs_value(states,i,(j-1),bit_value); + + } + } + else { /* obtain next_state value */ + + if ( (1 + states->num_outputs + states->num_inputs) + == j ) { + /* skip the "->" token */ + } + else { + + /* convert to a floating point number... */ + cnv_get_spice_value(token,&number); + + states->next_state[i] = number; + } + } + } + } + } + } + else { /**** continuation type loop ****/ + + /* set state value to previous state value */ + states->state[i] = states->state[i-1]; + + /* set bits values to previous bits values */ + for (j=0; jnum_outputs; j++) { + + /*** Retrieve the previous bit value ***? + cm_get_bits_value(*states,i,j,&out); + + switch (out.state) { + + case ZERO: + switch (out.strength) { + + case STRONG: + bit_value = 0; + break; + + case RESISTIVE: + bit_value = 3; + break; + + case HI_IMPEDANCE: + bit_value = 6; + break; + + case UNDETERMINED: + bit_value = 9; + break; + } + break; + + case ONE: + switch (out.strength) { + + case STRONG: + bit_value = 1; + break; + + case RESISTIVE: + bit_value = 4; + break; + + case HI_IMPEDANCE: + bit_value = 7; + break; + + case UNDETERMINED: + bit_value = 10; + break; + } + break; + + case UNKNOWN: + switch (out.strength) { + + case STRONG: + bit_value = 2; + break; + + case RESISTIVE: + bit_value = 5; + break; + + case HI_IMPEDANCE: + bit_value = 8; + break; + + case UNDETERMINED: + bit_value = 11; + break; + } + break; + + } + + /*** Store this bit value ***/ + + cm_store_bits_value(states,i,j,bit_value); + + } + + for (j=0; j<(2 + states->num_inputs); j++) { + + token = CNVget_token(&s, &type); + + + if ( j < states->num_inputs ) { + + /* preset this bit location */ + bit_value = 3; + + if (0 == strcmp(token,"0")) bit_value = 0; + if (0 == strcmp(token,"1")) bit_value = 1; + if (0 == strcmp(token,"x")) bit_value = 2; + if (0 == strcmp(token,"X")) bit_value = 2; + + /* if this bit was not recognized, return with an error */ + if (3 == bit_value) { + return 1; + } + else { /* need to store this value in the inputs[] array */ + + cm_store_inputs_value(states,i,j,bit_value); + + } + } + else { /* obtain next_state value */ + + if ( states->num_inputs == j ) { + /* skip the "->" token */ + } + else { + + /* convert to a floating point number... */ + cnv_get_spice_value(token,&number); + + states->next_state[i] = number; + } + } + } + + } + i++; + } + s = temp; + } + } + return 0; +} + + + + + +/*============================================================================== + +FUNCTION cm_d_state() + +AUTHORS + + 17 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 20 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_state code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_STATE ROUTINE ==============*/ + +/************************************************ +* The following is the model for the * +* digital state machine for the * +* ATESSE Version 2.0 system. * +* * +* Created 7/17/91 * +* Last Modified 8/20/91 J.P.Murray * +************************************************/ + + +void cm_d_state(ARGS) +{ + int i, /* generic loop counter index */ + j, /* generic loop counter index */ + err, /* integer for storage of error status */ + test; /* testing integer */ + + State_Table_t *states; /* pointer to base address structure + for all state arrays. *states + contains the pointers to + state[], bits[], input[] + and next_state[] arrays. These + arrays are allocated using + calloc, so they do not take up + rotational storage space...only + the *states structure does this. */ + + FILE *state_file; /* pointer to the state.in input + vector file */ + + Digital_t in, /* storage for each input bit */ + out; /* storage for each output bit */ + + Digital_State_t *clk, /* storage for clock value */ + *clk_old, /* previous clock value */ + *reset, /* current reset value */ + *reset_old; /* previous reset value */ + + + + char temp[MAX_STRING_SIZE], /* holding string variable for testing + input from state.in */ + *s; /* main string variable */ + + char *loading_error = "\n***ERROR***\nD_STATE: state.in file was not read successfully. \nThe most common cause of this problem is a\ntrailing blank line in the state.in file \n"; + + char *index_error = "\n***ERROR***\nD_STATE: An error exists in the ordering of states values\n in the states->state[] array. This is usually caused \nby non-contiguous state definitions in the state.in file \n"; + + + + + + /****** Setup required state variables ******/ + + if(INIT) { /* initial pass */ + + + /*** open file and count the number of vectors in it ***/ + state_file = fopen( PARAM(state_file), "r"); + + /* increment counter if not a comment until EOF reached... */ + i = 0; + s = temp; + while ( fgets(s,MAX_STRING_SIZE,state_file) != NULL) { + if ( '*' != s[0] ) { + while(isspace(*s) || (*s == '*')) + (s)++; + if ( *s != '\0' ) i++; + } + s = temp; + } + + /*** allocate storage for *states... ***/ + + states = (State_Table_t *) cm_event_alloc(0,sizeof(State_Table_t)); + + /* Store depth value */ + states->depth = i; + + /* Retrieve widths for bits[] and inputs[] */ + states->num_inputs = PORT_SIZE(in); + states->num_outputs = PORT_SIZE(out); + + + /* assign storage for arrays to pointers in states table */ + states->state = (int *) calloc(states->depth,sizeof(int)); + states->bits = (short *) calloc((states->num_outputs * states->depth / 4),sizeof(short)); + states->inputs = (short *) calloc((states->num_inputs * states->depth / 8),sizeof(short)); + states->next_state = (int *) calloc(states->depth,sizeof(int)); + + + /* Initialize *state, *bits, *inputs & *next_state to zero */ + for (i=0; idepth; i++) { + states->state[i] = 0; + states->next_state[i] = 0; + } + for (i=0; i<(test=(states->num_outputs * states->depth)/4); i++) states->bits[i] = 0; + for (i=0; i<(test=(states->num_inputs * states->depth)/8); i++) states->inputs[i] = 0; + + + + /*** allocate storage for *clk, *clk_old, *reset & *reset_old... ***/ + clk = clk_old = (Digital_State_t *) cm_event_alloc(1,sizeof(Digital_State_t)); + + reset = reset_old = (Digital_State_t *) cm_event_alloc(2,sizeof(Digital_State_t)); + + + + /*** Send file pointer and the four storage pointers ***/ + /*** to "cm_read_state_file()". This will return after ***/ + /*** reading the contents of state.in, and if no ***/ + /*** errors have occurred, the "*state" and "*bits" ***/ + /*** "*inputs", and "*next_state" vectors will be loaded ***/ + /*** and the num_inputs, num_outputs and depth ***/ + /*** values supplied. ***/ + + rewind(state_file); + err = cm_read_state_file(state_file,states); + + + if (err) { /* problem occurred in load...send error msg. */ + + cm_message_send(loading_error); + + /* Reset arrays to zero */ + for (i=0; idepth; i++) { + states->state[i] = 0; + states->next_state[i] = 0; + } + for (i=0; i<(test=(states->num_outputs * states->depth)/4); i++) states->bits[i] = 0; + for (i=0; i<(test=(states->num_inputs * states->depth)/8); i++) states->inputs[i] = 0; + + return; + } + + /* close state_file */ + fclose(state_file); + + + /* declare load values */ + + for (i=0; inum_outputs; i++) { + LOAD(in[i]) = PARAM(input_load); + } + + LOAD(clk) = PARAM(clk_load); + + LOAD(reset) = PARAM(reset_load); + + } + else { /**** Retrieve previous values ****/ + + states = (State_Table_t *) cm_event_get_ptr(0,0); + + clk = (Digital_State_t *) cm_event_get_ptr(1,0); + clk_old = (Digital_State_t *) cm_event_get_ptr(1,1); + + reset = (Digital_State_t *) cm_event_get_ptr(2,0); + reset_old = (Digital_State_t *) cm_event_get_ptr(2,1); + + } + + + + /******* Determine analysis type and output appropriate values *******/ + + if ( 0.0 == TIME ) { /****** DC analysis...output w/o delays ******/ + + /* set current state to default */ + states->current_state = PARAM(reset_state); + + /* set indices for this state */ + err = cm_set_indices(states); + if ( err == TRUE ) { + cm_message_send(index_error); + return; + } + + + /* Output new values... */ + for (i=0; inum_outputs; i++) { + + /* retrieve output value */ + cm_get_bits_value(states,states->index0,i,&out); + + OUTPUT_STATE(out[i]) = out.state; + OUTPUT_STRENGTH(out[i]) = out.strength; + } + } + + else { /****** Transient Analysis ******/ + + /*** load current input values if reset + is not connected, set to zero... ***/ + *clk = INPUT_STATE(clk); + + if ( PORT_NULL(reset) ) { + *reset = *reset_old = ZERO; + } + else { + *reset = INPUT_STATE(reset); + } + + + + /***** Find input that has changed... *****/ + + /**** Test reset value for change ****/ + if ( *reset != *reset_old ) { /* either reset or reset release */ + switch ( *reset ) { + + case ONE: + states->current_state = PARAM(reset_state); + + /* set indices for this state */ + err = cm_set_indices(states); + if ( err == TRUE ) { + cm_message_send(index_error); + return; + } + + /* Output new values... */ + for (i=0; inum_outputs; i++) { + + /* retrieve output value */ + cm_get_bits_value(states,states->index0,i,&out); + + OUTPUT_STATE(out[i]) = out.state; + OUTPUT_STRENGTH(out[i]) = out.strength; + OUTPUT_DELAY(out[i]) = PARAM(reset_delay); + } + break; + + case ZERO: + case UNKNOWN: + /* output remains at current value */ + for (i=0; inum_outputs; i++) { + OUTPUT_CHANGED(out[i]) = FALSE; + } + break; + + } + } + else { + + if ( ONE != *reset ) { + /**** model is not held to reset value ****/ + /**** Test clk value for change ****/ + if (*clk != *clk_old) { /* clock or clock release */ + switch ( *clk ) { + + case ONE: + + /** active edge...need to find out if a match **/ + /** exists between the current inputs and **/ + /** any of the inputs which drive the state **/ + /** machine to the next state...if so, we **/ + /** will need to retrieve that state value, **/ + /** and set the new index boundaries... **/ + + /* for each of the entries for the current_state... */ + for (i=states->index0; i<=states->indexN; i++) { + + /* first set err to zero... */ + err = 0; + + /* for each bit of the inputs value for this + entry...*/ + for (j=0; jnum_inputs; j++) { + + /* retrieve the current input bit... */ + in.state = INPUT_STATE(in[j]); + + /* ...& compare to the corresponding + inputs[i] value. */ + err = cm_compare_to_inputs(states,i,j,in.state); + + /* break if comparison was no-good... */ + if ( 0 != err ) break; + + } + + /* if the comparison of the entire input + word was good, break out of this loop too... */ + if ( 0 == err ) break; + } + + /* if err == 0, then a match was found...otherwise, + we will not change states... */ + + if ( 0 == err ) { + + /* use "i" to retrieve the next state value: + store this into current_state... */ + states->current_state = states->next_state[i]; + + /* set indices for this new state */ + err = cm_set_indices(states); + if ( err == TRUE ) { + cm_message_send(index_error); + return; + } + + /* Output new values... */ + for (i=0; inum_outputs; i++) { + + /* retrieve output value */ + cm_get_bits_value(states,states->index0,i,&out); + + OUTPUT_STATE(out[i]) = out.state; + OUTPUT_STRENGTH(out[i]) = out.strength; + OUTPUT_DELAY(out[i]) = PARAM(clk_delay); + } + + } + else { /* no change in state or in output */ + + for (i=0; inum_outputs; i++) { + OUTPUT_CHANGED(out[i]) = FALSE; + } + + } + + break; + + case ZERO: + case UNKNOWN: + + /* no change in state or in output */ + for (i=0; inum_outputs; i++) { + OUTPUT_CHANGED(out[i]) = FALSE; + } + + break; + } + } + else { /* input value must have changed... + return previous output value. */ + + for (i=0; inum_outputs; i++) { + OUTPUT_CHANGED(out[i]) = FALSE; + } + } + } + else { /* Reset is active... + return previous output values. */ + + for (i=0; inum_outputs; i++) { + OUTPUT_CHANGED(out[i]) = FALSE; + } + + } + } + } +} + + + diff --git a/src/xspice/icm/digital/d_state/d_state.h b/src/xspice/icm/digital/d_state/d_state.h new file mode 100644 index 000000000..a62fe5f1b --- /dev/null +++ b/src/xspice/icm/digital/d_state/d_state.h @@ -0,0 +1,77 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_state/d_state.h + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 13 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 20 Aug 1991 Jeffrey P. Murray + 30 Sep 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the header information for the + d_state model. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + + +REFERENCED FILES + + N/A + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + +#define OK 0 +#define FAIL 1 + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + +typedef char line_t[82]; /* A SPICE size line. <= 80 characters plus '\n\0' */ + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + diff --git a/src/xspice/icm/digital/d_state/ifspec.ifs b/src/xspice/icm/digital/d_state/ifspec.ifs new file mode 100644 index 000000000..c4b76cdeb --- /dev/null +++ b/src/xspice/icm/digital/d_state/ifspec.ifs @@ -0,0 +1,130 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_state (state machine) code model. + +===============================================================================*/ + + +NAME_TABLE: + + +C_Function_Name: cm_d_state +Spice_Model_Name: d_state +Description: "digital state machine" + + +PORT_TABLE: + + +Port_Name: in clk +Description: "input" "clock" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: yes no +Vector_Bounds: - - +Null_Allowed: yes no + + +PORT_TABLE: + + +Port_Name: reset out +Description: "reset" "output" +Direction: in out +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no yes +Vector_Bounds: - [1 -] +Null_Allowed: yes no + + + +PARAMETER_TABLE: + + +Parameter_Name: clk_delay reset_delay +Description: "delay from CLK" "delay from reset" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + + +Parameter_Name: state_file +Description: "state transition specification file name" +Data_Type: string +Default_Value: "state.txt" +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + + +Parameter_Name: reset_state +Description: "default state on RESET & at DC" +Data_Type: int +Default_Value: 0 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + + +Parameter_Name: input_load +Description: "input loading capacitance (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + + +Parameter_Name: clk_load +Description: "clock loading capacitance (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: no +PARAMETER_TABLE: + + +Parameter_Name: reset_load +Description: "reset loading capacitance (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: no + diff --git a/src/xspice/icm/digital/d_tff/cfunc.mod b/src/xspice/icm/digital/d_tff/cfunc.mod new file mode 100644 index 000000000..b6069e8b7 --- /dev/null +++ b/src/xspice/icm/digital/d_tff/cfunc.mod @@ -0,0 +1,698 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_tff/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 24 June 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 12 Aug 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + 29 Jan 1992 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the d_tff code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*=============================================================================*/ + +/*=== CM ROUTINE ===*/ + + + + +/*============================================================================== + +FUNCTION cm_toggle_bit() + + +AUTHORS + + 27 Sept 1991 Jeffrey P. Murray + + +MODIFICATIONS + + NONE + + +SUMMARY + + Alters the state of a passed digital variable to its + complement. Thus, a ONE changes to a ZERO. A ZERO changes + to a ONE, and an UNKNOWN remains unchanged. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + No returned value. Passed pointer to variable is used + to redefine the variable value. + + +GLOBAL VARIABLES + + NONE + + +NON-STANDARD FEATURES + + NONE + +/*=============================================================================*/ + +/*=== CM_TOGGLE_BIT ROUTINE ===*/ + +static void cm_toggle_bit(Digital_State_t *bit) + +{ + /* Toggle bit from ONE to ZERO or vice versa, unless the + bit value is UNKNOWN. In the latter case, return + without changing the bit value. */ + + if ( UNKNOWN != *bit ) { + if ( ONE == *bit ) { + *bit = ZERO; + } + else { + *bit = ONE; + } + } + +} + + + +/*============================================================================== + +FUNCTION cm_d_tff() + + +AUTHORS + + 24 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 29 Jan 1992 Jeffrey P. Murray + + +SUMMARY + + This function implements the d_tff code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + + +GLOBAL VARIABLES + + NONE + + +NON-STANDARD FEATURES + + NONE + +/*=============================================================================*/ + +/*=== CM_D_TFF ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital t-type flip flop for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/24/91 J.P.Murray * +************************************************/ + + +void cm_d_tff(ARGS) + +{ + int i; /* generic loop counter index */ + + + Digital_State_t *clk, /* current clk value */ + *clk_old, /* previous clk value */ + *set, /* current set value for dff */ + *set_old, /* previous set value for dff */ + *reset, /* current reset value for dff */ + *reset_old, /* previous reset value for dff */ + *out, /* current output for dff */ + *out_old, /* previous output for dff */ + + toggle_input, /* current toggle input value */ + + temp; /* temp storage for state values */ + + + + /*** Setup required state variables ***/ + + if(INIT) { /* initial pass */ + + /* allocate storage */ + clk = clk_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + set = set_old = (Digital_State_t *) cm_event_alloc(1,sizeof(Digital_State_t)); + reset = reset_old = (Digital_State_t *) cm_event_alloc(2,sizeof(Digital_State_t)); + out = out_old = (Digital_State_t *) cm_event_alloc(3,sizeof(Digital_State_t)); + + /* declare load values */ + LOAD(t) = PARAM(t_load); + LOAD(clk) = PARAM(clk_load); + if ( !PORT_NULL(set) ) { + LOAD(set) = PARAM(set_load); + } + if ( !PORT_NULL(reset) ) { + LOAD(reset) = PARAM(reset_load); + } + + } + else { /* Retrieve previous values */ + + /* retrieve storage for the outputs */ + clk = (Digital_State_t *) cm_event_get_ptr(0,0); + clk_old = (Digital_State_t *) cm_event_get_ptr(0,1); + set = (Digital_State_t *) cm_event_get_ptr(1,0); + set_old = (Digital_State_t *) cm_event_get_ptr(1,1); + reset = (Digital_State_t *) cm_event_get_ptr(2,0); + reset_old = (Digital_State_t *) cm_event_get_ptr(2,1); + out = (Digital_State_t *) cm_event_get_ptr(3,0); + out_old = (Digital_State_t *) cm_event_get_ptr(3,1); + } + + + + /******** load current input values if set or reset + are not connected, set to zero... ********/ + *clk = INPUT_STATE(clk); + if ( PORT_NULL(set) ) { + *set = *set_old = ZERO; + } + else { + *set = INPUT_STATE(set); + } + if ( PORT_NULL(reset) ) { + *reset = *reset_old = ZERO; + } + else { + *reset = INPUT_STATE(reset); + } + + + + + + + /******* Determine analysis type and output appropriate values *******/ + + if (0.0 == TIME) { /****** DC analysis...output w/o delays ******/ + + temp = PARAM(ic); + + /** Modify output if set or reset lines are active **/ + if ( (*set==ONE) && (*reset==ZERO) ) temp = ONE; + if ( (*set==ZERO) && (*reset==ONE) ) temp = ZERO; + if ( (*set==ONE) && (*reset==ONE) ) temp = UNKNOWN; + + *out = *out_old = temp; + + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + } + + cm_toggle_bit(&temp); + + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = temp; + } + } + + else { /****** Transient Analysis ******/ + + + /***** Find input that has changed... *****/ + + /**** Test set value for change ****/ + if ( *set != *set_old ) { /* either set or set release */ + switch ( *set ) { + + case ONE: + if ( ONE != *reset) { + if (*out_old != ONE) { /* set will change output */ + /* output goes to ONE */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already set */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != UNKNOWN) { /* set will change output */ + /* output goes to UNKNOWN */ + *out = UNKNOWN; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = UNKNOWN; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = UNKNOWN; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case ZERO: + if ( ONE != *reset) { + /* output remains at current value */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + else { + if (*out_old != ZERO) { /* set will change output */ + /* output returns to reset condition */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case UNKNOWN: + if ( ONE == *reset ) { + /* output goes to ZERO */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(set_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(set_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + } + } + else { + + /**** Test reset value for change ****/ + if ( *reset != *reset_old ) { /* either reset or reset release */ + switch ( *reset ) { + + case ONE: + if ( ONE != *set) { + if (*out_old != ZERO) { /* reset will change output */ + /* output goes to ZERO */ + *out = ZERO; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ZERO; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ONE; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + else { + if (*out_old != UNKNOWN) { /* reset will change output */ + /* output goes to UNKNOWN */ + *out = UNKNOWN; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = UNKNOWN; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = UNKNOWN; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case ZERO: + if ( ONE != *set) { + /* output remains at current value */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + else { + if (*out_old != ONE) { /* reset will change output */ + /* output returns to set condition */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already reset */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + break; + + case UNKNOWN: + if ( ONE == *set ) { + /* output goes to ONE */ + *out = ONE; + + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = ONE; + OUTPUT_DELAY(out) = PARAM(reset_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = ZERO; + OUTPUT_DELAY(Nout) = PARAM(reset_delay); + } + } + else { + *out = *out_old; /* output already unknown */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + } + } + else { + + /**** Test clk value for change ****/ + if ( (*clk != *clk_old) && (*reset != ONE) && + (*set != ONE) ) { /* clock or clock release */ + switch ( *clk ) { + + case ONE: + /* active edge...calculate new data output */ + toggle_input = INPUT_STATE(t); + + switch (toggle_input) { + case ONE: + temp = *out_old; + cm_toggle_bit(&temp); + break; + case ZERO: + temp = *out_old; + break; + case UNKNOWN: + temp = UNKNOWN; + break; + } + + if (*out_old != temp) { /* clk will change output */ + *out = temp; + if ( !PORT_NULL(out) ) { + OUTPUT_STATE(out) = temp; + OUTPUT_DELAY(out) = PARAM(clk_delay); + } + + cm_toggle_bit(&temp); + + if ( !PORT_NULL(Nout) ) { + OUTPUT_STATE(Nout) = temp; + OUTPUT_DELAY(Nout) = PARAM(clk_delay); + } + } + else { + *out = *out_old; /* output same as before */ + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + break; + + case ZERO: + case UNKNOWN: + /* inactive edge...return previous values */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + break; + + } + } + + else { /* data value must have changed... + return previous output value. */ + *out = *out_old; + if ( !PORT_NULL(out) ) { + OUTPUT_CHANGED(out) = FALSE; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_CHANGED(Nout) = FALSE; + } + } + } + } + + + /***** Add additional rise or fall delays, if appropriate *****/ + + if ( *out != *out_old ) { /*** output value is changing ***/ + + switch ( *out ) { + + /** fall to zero value **/ + case 0: + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(fall_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(rise_delay); + } + break; + + /** rise to one value **/ + case 1: + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(rise_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(fall_delay); + } + break; + + /** unknown output **/ + default: + /* based on old value, add rise or fall delay */ + if (0 == *out_old) { /* add rising delay */ + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(rise_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(fall_delay); + } + } + else { /* add falling delay */ + if ( !PORT_NULL(out) ) { + OUTPUT_DELAY(out) += PARAM(fall_delay); + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_DELAY(Nout) += PARAM(rise_delay); + } + } + break; + } + } + } + + /*** output strength values ***/ + if ( !PORT_NULL(out) ) { + OUTPUT_STRENGTH(out) = STRONG; + } + if ( !PORT_NULL(Nout) ) { + OUTPUT_STRENGTH(Nout) = STRONG; + } +} + + + + + diff --git a/src/xspice/icm/digital/d_tff/ifspec.ifs b/src/xspice/icm/digital/d_tff/ifspec.ifs new file mode 100644 index 000000000..eb5ba21d1 --- /dev/null +++ b/src/xspice/icm/digital/d_tff/ifspec.ifs @@ -0,0 +1,123 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_tff code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_d_tff +Spice_Model_Name: d_tff +Description: "digital toggle flip flop" + + +PORT_TABLE: + +Port_Name: t clk +Description: "toggle input" "clock" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PORT_TABLE: + +Port_Name: set reset +Description: "asynch. set" "asynch. reset" +Direction: in in +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PORT_TABLE: + +Port_Name: out Nout +Description: "data output" "inverted data output" +Direction: out out +Default_Type: d d +Allowed_Types: [d] [d] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: clk_delay set_delay +Description: "delay from clk" "delay from set" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: reset_delay ic +Description: "delay from reset" "output initial state" +Data_Type: real int +Default_Value: 1.0e-9 0 +Limits: [1e-12 -] [0 2] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: rise_delay fall_delay +Description: "rise delay" "fall delay" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: t_load clk_load +Description: "toggle load value (F)" "clk load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: set_load reset_load +Description: "set load value (F)" "reset load value (F)" +Data_Type: real real +Default_Value: 1.0e-12 1.0e-12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + diff --git a/src/xspice/icm/digital/d_tristate/cfunc.mod b/src/xspice/icm/digital/d_tristate/cfunc.mod new file mode 100644 index 000000000..ea6ac6bba --- /dev/null +++ b/src/xspice/icm/digital/d_tristate/cfunc.mod @@ -0,0 +1,166 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_tristate/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 18 Nov 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 26 Nov 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the d_tristate + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_d_tristate() + +AUTHORS + + 18 Nov 1991 Jeffrey P. Murray + +MODIFICATIONS + + 26 Nov 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the d_tristate code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_D_TRISTATE ROUTINE ===*/ + +/************************************************ +* The following is a model for a simple * +* digital tristate for the ATESSE Version * +* 2.0 system. Note that this version has * +* a single delay for both input and enable... * +* a more realistic model is anticipated in * +* the not-so-distant future. * +* * +* Created 11/18/91 J.P,Murray * +* Last Modified 11/26/91 * +************************************************/ + + +void cm_d_tristate(ARGS) +{ + int enable; /* holding variable for enable input */ + + + + /* Retrieve input values and static variables */ + enable = INPUT_STATE(enable); + + OUTPUT_STATE(out) = INPUT_STATE(in); + OUTPUT_DELAY(out) = PARAM(delay); + + + /* define input loading... */ + LOAD(in) = PARAM(input_load); + LOAD(enable) = PARAM(enable_load); + + + + + if (ZERO == enable) { + + OUTPUT_STRENGTH(out) = HI_IMPEDANCE; + + } + else + if (UNKNOWN == enable) { + + OUTPUT_STRENGTH(out) = UNDETERMINED; + + } + else { + + OUTPUT_STRENGTH(out) = STRONG; + + } +} + + diff --git a/src/xspice/icm/digital/d_tristate/ifspec.ifs b/src/xspice/icm/digital/d_tristate/ifspec.ifs new file mode 100644 index 000000000..982a31fe5 --- /dev/null +++ b/src/xspice/icm/digital/d_tristate/ifspec.ifs @@ -0,0 +1,76 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 18 Nov 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + digital d_tristate code model. + +===============================================================================*/ + + +NAME_TABLE: + +Spice_Model_Name: d_tristate +C_Function_Name: cm_d_tristate +Description: "digital one-bit-wide tristate buffer" + + +PORT_TABLE: + +Port_Name: in enable out +Description: "input" "enable" "output" +Direction: in in out +Default_Type: d d d +Allowed_Types: [d] [d] [d] +Vector: no no no +Vector_Bounds: - - - +Null_Allowed: no no no + + +PARAMETER_TABLE: + +Parameter_Name: delay +Description: "delay" +Data_Type: real +Default_Value: 1.0e-9 +Limits: [1e-12 -] +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: input_load +Description: "input load value (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: enable_load +Description: "enable load value (F)" +Data_Type: real +Default_Value: 1.0e-12 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + + diff --git a/src/xspice/icm/digital/d_xnor/cfunc.mod b/src/xspice/icm/digital/d_xnor/cfunc.mod new file mode 100644 index 000000000..65beb0a15 --- /dev/null +++ b/src/xspice/icm/digital/d_xnor/cfunc.mod @@ -0,0 +1,322 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE d_xnor/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 18 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 7 Aug 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the d_xnor code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_toggle_bit() + + +AUTHORS + + 27 Sept 1991 Jeffrey P. Murray + + +MODIFICATIONS + + NONE + + +SUMMARY + + Alters the state of a passed digital variable to its + complement. Thus, a ONE changes to a ZERO. A ZERO changes + to a ONE, and an UNKNOWN remains unchanged. + + +INTERFACES + + FILE ROUTINE CALLED + + N/A N/A + + +RETURNED VALUE + + No returned value. Passed pointer to variable is used + to redefine the variable value. + + +GLOBAL VARIABLES + + NONE + + +NON-STANDARD FEATURES + + NONE + +/*=============================================================================*/ + +/*=== CM_TOGGLE_BIT ROUTINE ===*/ + +static void cm_toggle_bit(Digital_State_t *bit) + +{ + /* Toggle bit from ONE to ZERO or vice versa, unless the + bit value is UNKNOWN. In the latter case, return + without changing the bit value. */ + + if ( UNKNOWN != *bit ) { + if ( ONE == *bit ) { + *bit = ZERO; + } + else { + *bit = ONE; + } + } + +} + + +/*============================================================================== + +FUNCTION cm_d_xnor() + + +AUTHORS + + 18 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 7 Aug 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This function implements the d_xnor code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMutil.c void cm_toggle_bit(); + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + + +GLOBAL VARIABLES + + NONE + + +NON-STANDARD FEATURES + + NONE + +/*=============================================================================*/ + +/*=== CM_D_XNOR ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital XNOR gate for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/18/91 J.P.Murray * +************************************************/ + + +void cm_d_xnor(ARGS) + +{ + int i, /* generic loop counter index */ + size; /* number of input & output ports */ + + + + Digital_State_t *out, /* temporary output for buffers */ + *out_old, /* previous output for buffers */ + input; /* temp storage for input bits */ + + + /** Retrieve size value... **/ + size = PORT_SIZE(in); + + + + /*** Setup required state variables ***/ + + if(INIT) { /* initial pass */ + + /* allocate storage for the outputs */ + out = out_old = (Digital_State_t *) cm_event_alloc(0,sizeof(Digital_State_t)); + + for (i=0; i +#include +#include +#include + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_dac_bridge() + +AUTHORS + + 3 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 16 Aug 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the dac_bridge code model. + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_set_perm_bkpt() + + CMevt.c void *cm_event_alloc() + void *cm_event_get_ptr() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + + +/*=== CM_DAC_BRIDGE ROUTINE ===*/ + +/************************************************ +* The following is the model for the * +* digital-to-analog nodebridge for the * +* ATESSE Version 2.0 system. * +* * +* Created 6/3/91 J.P.Murray * +************************************************/ + + +void cm_dac_bridge(ARGS) + +{ + double out_low, /* analog output value corresponding to '0' + digital input */ + out_high, /* analog output value corresponding to '1' + digital input */ + out_undef, /* analog output value corresponding to 'U' + digital input */ + t_rise, /* rise time...used to produce d(out)/d(time) + values for gradual change in analog output. */ + t_fall, /* fall time...used to produce d(out)/d(time) + values for gradual change in analog output. */ + *out, /* array holding all output values */ + *out_old, /* array holding previous output values */ + fraction, /* fraction of total rise or fall time to add to + current time value for breakpoint calculation */ + level_inc, /* incremental level value out_high - out_low */ + rise_slope, /* level_inc divided by t_rise */ + fall_slope, /* level_inc divided by t_fall */ + time_inc, /* time increment since last analog call */ + test, /* testing variable */ + *breakpoint; /* holding variable to prevent infinite + posting of the same breakpoint */ + + + + int i, /* generic loop counter index */ + size; /* number of input & output ports */ + + + + Digital_State_t *in, /* base address of array holding all input + values */ + *in_old; /* array holding previous input values */ + + + + + + /* determine "width" of the node bridge... */ + + size = PORT_SIZE(in); + + + /** Read in remaining model parameters **/ + + out_low = PARAM(out_low); + out_high = PARAM(out_high); + t_rise = PARAM(t_rise); + t_fall = PARAM(t_fall); + + + /* Test to see if out_low and out_high were specified, but */ + /* out_undef was not... */ + /* if so, take out_undef as mean of out_high and out_low. */ + + if (!PARAM_NULL(out_low) && !PARAM_NULL(out_high) && + PARAM_NULL(out_undef) ) { + out_undef = out_low + (out_high - out_low) / 2.0; + } + else { + out_undef = PARAM(out_undef); + } + + + + if (INIT) { /*** Test for INIT == TRUE. If so, allocate storage, etc. ***/ + + + /* Allocate storage for inputs */ + in = in_old = (Digital_State_t *) cm_event_alloc(0,size * sizeof(Digital_State_t)); + + + /* Allocate storage for outputs */ + + /* retrieve previously-allocated discrete input and */ + /* allocate storage for analog output values. */ + + /* allocate output space and obtain adresses */ + out = out_old = cm_analog_alloc(0,size * sizeof(double)); + breakpoint = cm_analog_alloc(1,sizeof(double)); + + /* read current input values */ + for (i=0; i out_low) { /* output still dropping */ + + out[i] = out_old[i] - fall_slope*time_inc; + if ( out_low > out[i]) out[i]=out_low; + + } + else { /* output at out_low */ + + out[i] = out_low; + + } + break; + + case ONE: + if (out_old[i] < out_high) { /* output still rising */ + + out[i] = out_old[i] + rise_slope*time_inc; + if ( out_high < out[i]) out[i]=out_high; + + } + else { /* output at out_high */ + + out[i] = out_high; + + } + break; + + + case UNKNOWN: + if (out_old[i] < out_undef) { /* output still rising */ + + out[i] = out_old[i] + (rise_slope * time_inc); + if ( out_undef < out[i]) out[i]=out_undef; + + } + else { + + if (out_old[i] > out_undef) { /* output still falling */ + + out[i] = out_old[i] - fall_slope*time_inc; + if ( out_undef > out[i]) out[i]=out_undef; + } + else { /* output at out_undef */ + + out[i] = out_undef; + } + + } + + break; + + } + } + else { /* There HAS been a change in this digital input + since the last analog access...need to use the + old value of input to complete the breakpoint + slope before changing directions... */ + + + switch (in_old[i]) { + + case ZERO: + if (out_old[i] > out_low) { /* output still dropping */ + + out[i] = out_old[i] - fall_slope*time_inc; + if ( out_low > out[i]) out[i]=out_low; + + } + else { /* output at out_low */ + + out[i] = out_low; + + } + break; + + case ONE: + if (out_old[i] < out_high) { /* output still rising */ + + out[i] = out_old[i] + rise_slope*time_inc; + if ( out_high < out[i]) out[i]=out_high; + + } + else { /* output at out_high */ + + out[i] = out_high; + + } + break; + + + case UNKNOWN: + if (out_old[i] < out_undef) { /* output still rising */ + + out[i] = out_old[i] + (rise_slope * time_inc); + if ( out_undef < out[i]) out[i]=out_undef; + + } + else { + + if (out_old[i] > out_undef) { /* output still falling */ + + out[i] = out_old[i] - fall_slope*time_inc; + if ( out_undef > out[i]) out[i]=out_undef; + } + else { /* output at out_undef */ + + out[i] = out_undef; + } + + } + + break; + + } + + + + /* determine required new breakpoint for the end of + the output analog transition & post */ + + switch (in[i]) { + + case ONE: /* rising for all outputs */ + fraction = (out_high - out[i]) / (out_high - out_low); + test = TIME + (fraction * t_rise); + cm_analog_set_perm_bkpt(test); + break; + + case UNKNOWN: /* may be rising or falling */ + + if ( out_undef > out[i] ) { /* rising to U */ + fraction = (out_undef - out[i]) / (out_high - out_low); + test = TIME + (fraction * t_rise); + cm_analog_set_perm_bkpt(test); + } + else { /* falling to U */ + fraction = (out[i] - out_undef) / (out_high - out_low); + test = TIME + (fraction * t_fall); + cm_analog_set_perm_bkpt(test); + } + break; + + case ZERO: /* falling for all outputs */ + fraction = (out[i] - out_low) / (out_high - out_low); + test = TIME + (fraction * t_fall); + cm_analog_set_perm_bkpt(test); + break; + } + } + } + + /* Output values... */ + + for (i=0; i 1" "fall time 1 -> 0" +Data_Type: real real +Default_Value: 1.0e-9 1.0e-9 +Limits: [1e-12 -] [1e-12 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes diff --git a/src/xspice/icm/digital/modpath.lst b/src/xspice/icm/digital/modpath.lst new file mode 100644 index 000000000..65d9f32c9 --- /dev/null +++ b/src/xspice/icm/digital/modpath.lst @@ -0,0 +1,27 @@ +adc_bridge +dac_bridge +d_and +d_buffer +d_dff +d_dlatch +d_fdiv +d_inverter +d_jkff +d_nand +d_nor +d_open_c +d_open_e +d_or +d_osc +d_pulldown +d_pullup +d_ram +d_source +d_srff +d_srlatch +d_state +d_tff +d_tristate +d_xnor +d_xor + diff --git a/src/xspice/icm/digital/udnpath.lst b/src/xspice/icm/digital/udnpath.lst new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/src/xspice/icm/digital/udnpath.lst @@ -0,0 +1,2 @@ + + diff --git a/src/xspice/icm/makedefs.in b/src/xspice/icm/makedefs.in new file mode 100644 index 000000000..5c56f042f --- /dev/null +++ b/src/xspice/icm/makedefs.in @@ -0,0 +1,40 @@ +# Edit this file to set global include paths, +# compiler info and subdirs + +# Directory sturcture +SHELL = @SHELL@ +srcdir = @srcdir@ +top_builddir = ../../.. +top_srcdir = @top_srcdir@ +subdir = src/xspice/icm + +# C compiler to use +CC = @CC@ + +# Spice header include path +INCLUDES = -I$(TOPDIR)$(top_srcdir)/src/include -I$(TOPDIR)$(top_builddir) + +# CFLAGS to use here +CFLAGS = @CFLAGS@ -fPIC -DCM_LINUX + +# Path to the cmpp utility +CMPP = $(TOPDIR)$(top_builddir)/src/xspice/cmpp/cmpp + +# Flags to use when linking shared library +LDFLAGS = -shared + +# The codemodels to make +CMDIRS = spice2poly digital analog xtradev xtraevt + +# Install instructions + +# or use mkdir -p +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ + diff --git a/src/xspice/icm/spice2poly/icm_spice2poly/README b/src/xspice/icm/spice2poly/icm_spice2poly/README new file mode 100644 index 000000000..c850128a6 --- /dev/null +++ b/src/xspice/icm/spice2poly/icm_spice2poly/README @@ -0,0 +1,49 @@ +This directory holds a codemodel which enables ngspice to handle SPICE +2 POLY attributes on controlled sources. In short, when a SPICE 2 +netlist is read in, any controlled sources with POLY attributes are +translated into codemodel devices with an associated .model which +invokes spice2poly to evaluate the polynomial. + +To use this model, you need to do the following: + +1. Compile the rest of ngspice/tclspice in the usual way from the +base directory. + +2. Download and install SPICE Opus (available from +http://www.fe.uni-lj.si/ ). From this you need the program cmpp, as +well as some of the include files. + +3. Edit the Makefile in this directory and make the variable CMPPDIR +point to the base location of your Opus installation. + +4. Edit the Makefile in the directory above (..) and make the +variable CMPDIR point to the base location of your Opus installation. + +5. Do "make" in the directory above (..). The makefiles are set up +to do all the necessary stuff to turn the spice2poly sources into a +shared object named spice2poly.cm which you can load into ngspice. +(Alternatively, you can do "make codemodels" from $(top_srcdir); I +have included codemodels as a target which cd's into the directory +below and does "make".) + +6. Read the codemodel into ngspice in the following way: + +ngspice 1 -> codemodel /usr/local/src/tclspice-0.2.10/src/xspice/icm/spice2poly.cm + +(Of course, you should point to the location where *you* built +spice2poly.cm!) You might want to put this invocation into your +spinit file (which usually lives in $(top_srcdir)/src/). + +7. Then read in your SPICE netlist. SPICE 2 POLY attributes in +controlled sources will be translated into .models invoking the +spice2poly codemodel. You should be able to run ngspice and simulate +in the usual way! + +---------------------------------------------------------------------- +Please send any comments/questions/bug reports to: + +Stuart Brorson +sdb@cloud9.net + +-- SDB 6.19.2003 + diff --git a/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod b/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod new file mode 100644 index 000000000..4bf354e20 --- /dev/null +++ b/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod @@ -0,0 +1,302 @@ +/* =========================================================================== +FILE cfunc.mod + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of a code model polynomial controlled + source compatible with SPICE 2G6 poly sources. + +INTERFACES + + spice2poly() + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +/* + +This code model implements the non-linear polynomial controlled sources +available in SPICE 2G6. An automatic translator added into the simulator +front end is used to map 2G6 syntax into a call to this model in the +required syntax. + +This model may also be called directly as follows: + + a1 [ ] xxx + .model xxx spice2poly ( coef = [ ] ) + +Refer to the 2G6 User Guide for an explanation of the coefficients. + + +This model is patterned after the FORTRAN code used in the 2G6 simulator. +Function cm_poly() below performs the functions of subroutines NLCSRC and +EVPOLY. Function evterm() performs the function of subroutine EVTERM, +and function nxtpwr() performs the function of subroutine NXTPWR. + +*/ + + + + +void *malloc(int); +void free(void *); + +/* SPICE 2G6 type utility functions */ +static double evterm(double x, int n); +static void nxtpwr(int *pwrseq, int pdim); + + + + +void spice2poly (ARGS) +{ + int num_inputs; /* Number of inputs to model */ + int num_coefs; /* Number of coefficients */ + int *exp; /* List of exponents in products */ + /* One for each input */ + + int i; /* Counter */ + int j; /* Counter */ + int k; /* Counter */ + + double *in; /* Values of inputs to model */ + double *coef; /* Values of coefficients */ + + double sum; /* Temporary for accumulating sum of terms */ + double product; /* Temporary for accumulating product */ + + double *acgains; /* Static variable holding AC gains for AC analysis */ + + + /* Get number of input values */ + + num_inputs = PORT_SIZE(in); + + /* If this is the first call to the model, allocate the static variable */ + /* array */ + + if(INIT) { + acgains = malloc(num_inputs * sizeof(double)); + for(i = 0; i < num_inputs; i++) + acgains[i] = 0.0; + STATIC_VAR(acgains) = acgains; + } + else + acgains = STATIC_VAR(acgains); + + /* If analysis type is AC, use the previously computed DC partials */ + /* for the AC gains */ + + if(ANALYSIS == MIF_AC) { + for(i = 0; i < num_inputs; i++) { + acgains = STATIC_VAR(acgains); + AC_GAIN(out,in[i]).real = acgains[i]; + AC_GAIN(out,in[i]).imag = 0.0; + } + return; + } + + /* Get input values and coefficients to local storage for faster access */ + + in = malloc(num_inputs * sizeof(double)); + for(i = 0; i < num_inputs; i++) + in[i] = INPUT(in[i]); + + num_coefs = PARAM_SIZE(coef); + + coef = malloc(num_coefs * sizeof(double)); + for(i = 0; i < num_coefs; i++) + coef[i] = PARAM(coef[i]); + + + /* Allocate the array of exponents used in computing the poly terms */ + exp = malloc(num_inputs * sizeof(int)); + + /* Initialize the exponents to zeros */ + for(i = 0; i < num_inputs; i++) + exp[i] = 0; + + + /* Compute the output of the source by summing the required products */ + for(i = 1, sum = coef[0]; i < num_coefs; i++) { + + /* Get the list of powers for the product terms in this term of the sum */ + nxtpwr(exp, num_inputs); + + /* Form the product of the inputs taken to the required powers */ + for(j = 0, product = 1.0; j < num_inputs; j++) + product *= evterm(in[j], exp[j]); + + /* Add the product times the appropriate coefficient into the sum */ + sum += coef[i] * product; + } + OUTPUT(out) = sum; + + + /* Compute and output the partials for each input */ + for(i = 0; i < num_inputs; i++) { + + /* Reinitialize the exponent list to zeros */ + for(j = 0; j < num_inputs; j++) + exp[j] = 0; + + /* Compute the partials by summing the required products */ + for(j = 1, sum = 0.0; j < num_coefs; j++) { + + /* Get the list of powers for the product terms in this term of the sum */ + nxtpwr(exp, num_inputs); + + /* If power for input for which partial is being evaluated */ + /* is zero, the term is a constant, so the partial is zero */ + if(exp[i] == 0) + continue; + + /* Form the product of the inputs taken to the required powers */ + for(k = 0, product = 1.0; k < num_inputs; k++) { + /* If input is not the one for which the partial is being taken */ + /* take the term to the specified exponent */ + if(k != i) + product *= evterm(in[k], exp[k]); + /* else, take the derivative of this term as n*x**(n-1) */ + else + product *= exp[k] * evterm(in[k], exp[k] - 1); + } + + /* Add the product times the appropriate coefficient into the sum */ + sum += coef[j] * product; + } + + PARTIAL(out,in[i]) = sum; + + /* If this is DC analysis, save the partial for use as AC gain */ + /* value in an AC analysis */ + + if(ANALYSIS == MIF_DC) + acgains[i] = sum; + } + + /* Free the allocated items and return */ + free(in); + free(coef); + free(exp); + + return; +} + + +/* Function evterm computes the value of x**n */ + +static double evterm( + double x, + int n) +{ + double product; /* Temporary accumlator for forming the product */ + + product = 1.0; + while(n > 0) { + product *= x; + n--; + } + + return(product); +} + + + +/* + +This function is a literal translation of subroutine NXTPWR in SPICE 2G6. +This was done to guarantee compatibility with the ordering of +coefficients used by 2G6. The 2G6 User Guide does not completely define +the algorithm used and the GOTO loaded FORTRAN code is difficult to unravel. +Therefore, a one-to-one translation was deemed the safest approach. + +No attempt is made to document the function statements since no documentaton +is available in the 2G6 code. However, it can be noted that the code +appears to generate the exponents of the product terms in the sum-of-products +produced by the following expansion for two and three dimensional polynomials: + + 2D (a + b) ** n + 3D (a + (b + c)) ** n + +where n begins at 1 and increments as needed for as many terms as there are +coefficients on the polynomial source SPICE deck card, and where terms that +are identical under the laws of associativity are dropped. Thus, for example, +the exponents for the following sums are produced: + + 2D a + b + a**2 + ab + b**2 + c**3 + ... + 3D a + b + c + a**2 + a*b + a*c + b**2 + bc + c**2 + a**3 + ... + +*/ + +/* Define a macro to tranlate between FORTRAN-style array references */ +/* and C-style array references */ + +#define PWRSEQ(x) pwrseq[x - 1] + + +static void nxtpwr( + int *pwrseq, /* Array of exponents */ + int pdim) +{ + int i; + int k; + int km1; + int psum; + + if(pdim == 1) goto stmt80; + k = pdim; +stmt10: if(PWRSEQ(k) != 0) goto stmt20; + k = k - 1; + if(k != 0) goto stmt10; + goto stmt80; +stmt20: if(k == pdim) goto stmt30; + PWRSEQ(k) = PWRSEQ(k) - 1; + PWRSEQ(k+1) = PWRSEQ(k+1) + 1; + goto stmt100; +stmt30: km1 = k - 1; + for(i = 1; i <= km1; i++) + if(PWRSEQ(i) != 0) goto stmt50; +stmt40: PWRSEQ(1) = PWRSEQ(pdim) + 1; + PWRSEQ(pdim) = 0; + goto stmt100; +stmt50: psum = 1; + k = pdim; +stmt60: if(PWRSEQ(k-1) >= 1) goto stmt70; + psum = psum + PWRSEQ(k); + PWRSEQ(k) = 0; + k = k - 1; + goto stmt60; +stmt70: PWRSEQ(k) = PWRSEQ(k) + psum; + PWRSEQ(k-1) = PWRSEQ(k-1) - 1; + goto stmt100; +stmt80: PWRSEQ(1) = PWRSEQ(1) + 1; + +stmt100: return; + +} + diff --git a/src/xspice/icm/spice2poly/icm_spice2poly/ifspec.ifs b/src/xspice/icm/spice2poly/icm_spice2poly/ifspec.ifs new file mode 100644 index 000000000..33da52236 --- /dev/null +++ b/src/xspice/icm/spice2poly/icm_spice2poly/ifspec.ifs @@ -0,0 +1,75 @@ +/* =========================================================================== +FILE ifspec.ifs + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of a code model polynomial controlled + source compatible with SPICE 2G6 poly sources. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +NAME_TABLE: + +Spice_Model_Name: spice2poly +C_Function_Name: spice2poly +Description: "2G6 compatible polynomial controlled source" + + +PORT_TABLE: + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: vd vd +Allowed_Types: [vd,id,vnam] [vd,id] +Vector: yes no +Vector_Bounds: [1 -] - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: coef +Description: "2G6 compatible spice card coefficient list" +Data_Type: real +Default_Value: - +Limits: - +Vector: yes +Vector_Bounds: [2 -] +Null_Allowed: no + + +STATIC_VAR_TABLE: + +Static_Var_Name: acgains +Data_Type: pointer +Description: "Partial derivatives from DC analysis used for AC gains" diff --git a/src/xspice/icm/spice2poly/modpath.lst b/src/xspice/icm/spice2poly/modpath.lst new file mode 100644 index 000000000..eba74545a --- /dev/null +++ b/src/xspice/icm/spice2poly/modpath.lst @@ -0,0 +1 @@ +icm_spice2poly diff --git a/src/xspice/icm/spice2poly/udnpath.lst b/src/xspice/icm/spice2poly/udnpath.lst new file mode 100644 index 000000000..e69de29bb diff --git a/src/xspice/icm/xtradev/aswitch/cfunc.mod b/src/xspice/icm/xtradev/aswitch/cfunc.mod new file mode 100644 index 000000000..07d8d3060 --- /dev/null +++ b/src/xspice/icm/xtradev/aswitch/cfunc.mod @@ -0,0 +1,186 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE aswitch/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 June 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 26 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the aswitch + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + + +/*============================================================================== + +FUNCTION cm_aswitch() + +AUTHORS + + 6 June 1991 Jeffrey P. Murray + +MODIFICATIONS + + 26 Sept 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the aswitch code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_ASWITCH ROUTINE ===*/ + + + +void cm_aswitch(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + double cntl_on; /* voltage above which switch come on */ + double cntl_off; /* voltage below the switch has resistance roff */ + double r_on; /* on resistance */ + double r_off; /* off resistance */ + double intermediate; /* intermediate value used to calculate + the resistance of the switch when the + controlling voltage is between cntl_on + and cntl_of */ + double r; /* value of the resistance of the switch */ + double pi_pvout; /* partial of the output wrt input */ + double pi_pcntl; /* partial of the output wrt control input */ + + Mif_Complex_t ac_gain; + + char *cntl_error = "\n*****ERROR*****\nASWITCH: CONTROL voltage delta less than 1.0e-12\n"; + + + /* Retrieve frequently used parameters... */ + + cntl_on = PARAM(cntl_on); + cntl_off = PARAM(cntl_off); + r_on = PARAM(r_on); + r_off = PARAM(r_off); + + if( r_on < 1.0e-3 ) r_on = 1.0e-3; /* Set minimum 'ON' resistance */ + + if( (fabs(cntl_on - cntl_off) < 1.0e-12) ) { + cm_message_send(cntl_error); + return; + } + + if ( PARAM(log) == MIF_TRUE ) { /* Logarithmic Variation in 'R' */ + intermediate = log(r_off / r_on) / (cntl_on - cntl_off); + r = r_on * exp(intermediate * (cntl_on - INPUT(cntl_in))); + pi_pvout = 1.0 / r; + pi_pcntl = intermediate * INPUT(out) / r; + } + else { /* Linear Variation in 'R' */ + intermediate = (r_on - r_off) / (cntl_on - cntl_off); + r = INPUT(cntl_in) * intermediate + ((r_off*cntl_on - + r_on*cntl_off) / (cntl_on - cntl_off)); + pi_pvout = 1.0 / r; + pi_pcntl = -intermediate * INPUT(out) / (r*r); + } + + pi_pvout = 1.0 / r; + + + if(ANALYSIS != MIF_AC) { /* Output DC & Transient Values */ + OUTPUT(out) = INPUT(out) / r; /* Note that the minus */ + PARTIAL(out,out) = pi_pvout; /* Signs are required */ + PARTIAL(out,cntl_in) = pi_pcntl; /* because current is */ + /* positive flowing INTO */ + /* rather than OUT OF a */ + /* component node. */ + } + else { /* Output AC Gain Values */ + ac_gain.real = -pi_pvout; /* See comment on minus */ + ac_gain.imag= 0.0; /* signs above.... */ + AC_GAIN(out,out) = ac_gain; + + ac_gain.real = -pi_pcntl; + ac_gain.imag= 0.0; + AC_GAIN(out,cntl_in) = ac_gain; + } +} + diff --git a/src/xspice/icm/xtradev/aswitch/ifspec.ifs b/src/xspice/icm/xtradev/aswitch/ifspec.ifs new file mode 100644 index 000000000..fb4f74713 --- /dev/null +++ b/src/xspice/icm/xtradev/aswitch/ifspec.ifs @@ -0,0 +1,76 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 26 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog aswitch code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_aswitch +Spice_Model_Name: aswitch +Description: "analog switch" + + +PORT_TABLE: + + +Port_Name: cntl_in out +Description: "input" "resistive output" +Direction: in inout +Default_Type: v gd +Allowed_Types: [v,vd,i,id,vnam] [gd] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + + +Parameter_Name: cntl_off cntl_on +Description: "control 'off' val" "control 'on' val" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: log r_off +Description: "Log-linear switch" "off resistance" +Data_Type: boolean real +Default_Value: TRUE 1.0e12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + +Parameter_Name: r_on +Description: "on resistance" +Data_Type: real +Default_Value: 1.0 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes diff --git a/src/xspice/icm/xtradev/capacitor/cfunc.mod b/src/xspice/icm/xtradev/capacitor/cfunc.mod new file mode 100644 index 000000000..53724e130 --- /dev/null +++ b/src/xspice/icm/xtradev/capacitor/cfunc.mod @@ -0,0 +1,91 @@ +/* =========================================================================== +FILE cfunc.mod + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of a capacitor code model + with voltage type initial conditions. + +INTERFACES + + cm_capacitor() + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +void *malloc(int); +void free(void *); + + +#define VC 0 + + +void cm_capacitor (ARGS) +{ + Complex_t ac_gain; + double partial; + double ramp_factor; + double *vc; + + + /* Get the ramp factor from the .option ramptime */ + ramp_factor = cm_analog_ramp_factor(); + + /* Initialize/access instance specific storage for capacitor voltage */ + if(INIT) { + vc = cm_analog_alloc(VC, sizeof(double)); + *vc = PARAM(ic) * cm_analog_ramp_factor(); + } + else { + vc = cm_analog_get_ptr(VC, 0); + } + + /* Compute the output */ + if(ANALYSIS == DC) { + OUTPUT(cap) = PARAM(ic) * ramp_factor; + PARTIAL(cap, cap) = 0.0; + } + else if(ANALYSIS == AC) { + ac_gain.real = 0.0; + ac_gain.imag = -1.0 / RAD_FREQ / PARAM(c); + AC_GAIN(cap, cap) = ac_gain; + } + else if(ANALYSIS == TRANSIENT) { + if(ramp_factor < 1.0) { + *vc = PARAM(ic) * ramp_factor; + OUTPUT(cap) = *vc; + PARTIAL(cap, cap) = 0.0; + } + else { + cm_analog_integrate(INPUT(cap) / PARAM(c), vc, &partial); + partial /= PARAM(c); + OUTPUT(cap) = *vc; + PARTIAL(cap, cap) = partial; + } + } +} + diff --git a/src/xspice/icm/xtradev/capacitor/ifspec.ifs b/src/xspice/icm/xtradev/capacitor/ifspec.ifs new file mode 100644 index 000000000..9e44efcb5 --- /dev/null +++ b/src/xspice/icm/xtradev/capacitor/ifspec.ifs @@ -0,0 +1,71 @@ +/* =========================================================================== +FILE ifspec.ifs + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of a capacitor code model + with voltage type initial conditions. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +NAME_TABLE: + +Spice_Model_Name: capacitor +C_Function_Name: cm_capacitor +Description: "Capacitor with voltage initial condition" + + +PORT_TABLE: + +Port_Name: cap +Description: "capacitor terminals" +Direction: inout +Default_Type: hd +Allowed_Types: [hd] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + +Parameter_Name: c ic +Description: "capacitance" "voltage initial condition" +Data_Type: real real +Default_Value: - 0.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + + diff --git a/src/xspice/icm/xtradev/cmeter/cfunc.mod b/src/xspice/icm/xtradev/cmeter/cfunc.mod new file mode 100644 index 000000000..74174794f --- /dev/null +++ b/src/xspice/icm/xtradev/cmeter/cfunc.mod @@ -0,0 +1,133 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE cmeter/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 30 July 1991 Bill Kuhn + + +MODIFICATIONS + + 26 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the cmeter + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmeters.c double cm_netlist_get_c() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + + +/*============================================================================== + +FUNCTION cm_cmeter() + +AUTHORS + + 30 July 1991 Bill Kuhn + +MODIFICATIONS + + 26 Sept 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the cmeter code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmeters.c double cm_netlist_get_c() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_CMETER ROUTINE ===*/ + +void cm_cmeter (ARGS) +{ + + double ceq; /* holding variable for read capacitance value */ + + if(INIT) { + ceq = cm_netlist_get_c(); + STATIC_VAR(c) = ceq; + } + else + ceq = STATIC_VAR(c); + + OUTPUT(out) = PARAM(gain) * ceq; + +} + + + + diff --git a/src/xspice/icm/xtradev/cmeter/ifspec.ifs b/src/xspice/icm/xtradev/cmeter/ifspec.ifs new file mode 100644 index 000000000..942ab0474 --- /dev/null +++ b/src/xspice/icm/xtradev/cmeter/ifspec.ifs @@ -0,0 +1,57 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 30 July 1991 Bill Kuhn + + +SUMMARY + + This file contains the interface specification file for the + analog cmeter code model. + +===============================================================================*/ + + +NAME_TABLE: + +Spice_Model_Name: cmeter +C_Function_Name: cm_cmeter +Description: "ATESSE 1 compatible capacitance meter" + + +PORT_TABLE: + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v, vd] [v, vd, i, id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: gain +Description: "C to voltage conversion factor" +Data_Type: real +Default_Value: 1.0 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +STATIC_VAR_TABLE: + +Static_Var_Name: c +Data_Type: real +Description: "capacitance connected to input node" + diff --git a/src/xspice/icm/xtradev/core/cfunc.mod b/src/xspice/icm/xtradev/core/cfunc.mod new file mode 100644 index 000000000..9829fb494 --- /dev/null +++ b/src/xspice/icm/xtradev/core/cfunc.mod @@ -0,0 +1,565 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE core/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 24 Apr 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 24 Apr 1991 Jeffrey P. Murray + 26 Sep 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the core + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CMutil.c void cm_smooth_corner(); + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include "core.h" + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION cm_core() + +AUTHORS + + 24 Apr 1991 Jeffrey P. Murray + +MODIFICATIONS + + 24 Apr 1991 Jeffrey P. Murray + 26 Sep 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the core code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + CMutil.c void cm_smooth_corner(); + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_CORE ROUTINE ===*/ + +/*******************************************************************/ +/* */ +/* CORE Model: */ +/* */ +/* The core model is designed to operate in one of two modes. */ +/* The first of these, and the one most likely to be used by */ +/* the engineer, is a modified version of the pwl model. This */ +/* behavior occurs when the model is in pwl mode (the default). */ +/* If the model is set to hyst mode, its behavior mimics that of */ +/* the hysteresis block. The following provides additional */ +/* detail: */ +/* */ +/* PWL Mode */ +/* */ +/* In pwl mode, the core model is a modified version of the */ +/* PWL model... */ +/* it has a single two-terminal input/output, and accepts as */ +/* input the mmf value, represented by a voltage. Its output is */ +/* a flux value, which is represented as a current. Additional */ +/* inputs include the cross-sectional area of the physical */ +/* core, and the median length of the core, seen from the */ +/* perspective of the flux that traverses it. */ +/* */ +/* The core model in pwl mode DOES NOT include hysteresis... */ +/* current thinking is that such provides */ +/* little benefit to the designer, aside from the ability to */ +/* calculate eddy losses in a modeled device...the nonlinear */ +/* B vs. H behavior, however, is of great importance. */ +/* */ +/* Note that the user must input a piece-wise-linear */ +/* description, in the form of a series of coordinate B vs. H */ +/* values, in order to model a particular core material type. */ +/* Such curves may be found in textbooks, or from manufacturer's */ +/* databooks. In this model, the "x" values are assumed to */ +/* represent the magnetic field (H), and the "y" values are */ +/* assumed to represent the flux density (B). */ +/* */ +/* Hyst Mode */ +/* */ +/* In hyst mode, the core model is a modified version of the */ +/* HYST code model... */ +/* it has a single two-terminal input/output, and accepts as */ +/* input the mmf value, represented by a voltage. Its output is */ +/* a flux value, which is represented as a current. Additional */ +/* inputs include the input high and low values for the */ +/* hysteretic behavior, and the output high and low values. */ +/* Also, a value of hysteresis must be included, as must an */ +/* input_domain value, and a fraction value, which tell the model */ +/* whether to interpret the input_domain as an absolute value */ +/* or as a relative figure. */ +/* */ +/* When the hyst mode is invoked on the core model, the user is */ +/* in the position of having to define reasonable values for the */ +/* upper and lower output limiting values. These can be very */ +/* difficule to nail down accurately. Current thinking is tha */ +/* the hysteresis capability will be of only nominal benefit to */ +/* the engineer, as it will not typically allow for as accurate */ +/* tailoring of the response as is possible in the pwl mode. */ +/* */ +/* 4/24/91 J.P.Murray */ +/* Last modified: 10/24/91 */ +/*******************************************************************/ + +void cm_core(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + + /*** The following declarations pertain to PWL mode ***/ + + int i; /* generic loop counter index */ + int size; /* size of the x_array */ + + int mode; /* mode parameter which determines whether + pwl or hyst will be used in analysis. */ + + + double input_domain; /* smoothing range */ + double *H; /* pointer to the H-field array */ + double *B; /* pointer to the B-field array */ + double lower_seg; /* x segment below which input resides */ + double upper_seg; /* x segment above which the input resides */ + double lower_slope; /* slope of the lower segment */ + double upper_slope; /* slope of the upper segment */ + double mmf_input; /* input mmf value */ + double H_input; /* calculated input H value */ + double B_out; /* output B value */ + double flux_out; /* calculated output flux */ + double dout_din; /* partial derivative of the output wrt input */ + double threshold_lower; /* value below which the output begins + smoothing */ + double threshold_upper; /* value above which the output begins smoothing */ + double area; /* cross-sectional area of the core (in meters)*/ + double length; /* length of core (in meters) */ + + Mif_Complex_t ac_gain; + + char *allocation_error="\n***ERROR***\nCORE: Allocation calloc failed!\n"; + char *limit_error="\n***ERROR***\nCORE: Violation of 50% rule in breakpoints!\n"; + + + + /*** The following declarations pertain to HYSTERESIS mode... ***/ + + double in, /* input to hysteresis block */ + out, /* output from hysteresis block */ + in_low, /* lower input value for hyst=0 at which + the transfer curve changes from constant + to linear */ + in_high, /* upper input value for hyst=0 at which + the transfer curve changes from constant + to linear */ + hyst, /* the hysteresis value (see above diagram) */ + out_lower_limit, /* the minimum output value from the block */ + out_upper_limit, /* the maximum output value from the block */ + slope, /* calculated rise and fall slope for the block */ + pout_pin, /* partial derivative of output w.r.t. input */ + x_rise_linear, /* = in_low + hyst */ + x_rise_zero, /* = in_high + hyst */ + x_fall_linear, /* = in_high - hyst */ + x_fall_zero; /* = in_low - hyst */ + + Boolean_t *hyst_state, /* TRUE => input is on lower leg of + hysteresis curve, between -infinity + and in_high + hyst. + FALSE => input is on upper leg + of hysteresis curve, between + in_low - hyst and +infinity */ + *old_hyst_state; /* previous value of *hyst_state */ + + + + + + + /* Retrieve mode parameter... */ + + mode = PARAM(mode); + + + /** Based on mode value, switch to the appropriate model code... **/ + + + /******** pwl mode *****************/ + if ( HYSTERESIS != mode ) { + + /* Retrieve frequently used parameters... */ + + input_domain = PARAM(input_domain); + area = PARAM(area); + length = PARAM(length); + + size = PARAM_SIZE(H_array); + + /* Allocate storage for breakpoint domain & range values */ + H = (double *) calloc(size, sizeof(double)); + if (H == '\0') { + cm_message_send(allocation_error); + return; + } + B = (double *) calloc(size, sizeof(double)); + if (B == '\0') { + cm_message_send(allocation_error); + return; + } + + + /* Retrieve H and B values. */ + for (i=0; i= (*(H+size-2) + *(H+size-1))/2.0) { + /*** H_input above highest midpoint ***/ + dout_din = (*(B+size-1) - *(B+size-2)) / + (*(H+size-1) - *(H+size-2)); + B_out = *(B+size-1) + (H_input - *(H+size-1)) * dout_din; + } + else { /*** H_input within bounds of end midpoints... ***/ + /*** must determine position progressively & then ***/ + /*** calculate required output. ***/ + + for (i=1; i= x_fall_linear + input_domain ) { /* Output @ upper limit */ + + out = out_upper_limit; + pout_pin = 0.0; + } + else { + if ( in >= x_fall_linear - input_domain ) { /* Upper smoothing region */ + cm_smooth_corner(in,x_fall_linear,out_upper_limit,input_domain, + slope,0.0,&out,&pout_pin); + } + else { + if (in >= x_fall_zero + input_domain) { /* Falling linear region */ + out = (in - x_fall_zero)*slope + out_lower_limit; + pout_pin = slope; + } + else { + if (in >= x_fall_zero - input_domain) { /* Lower smoothing region */ + cm_smooth_corner(in,x_fall_zero,out_lower_limit,input_domain, + 0.0,slope,&out,&pout_pin); + } + else { /* input has transitioned to X_RISING region... */ + out = out_lower_limit; + pout_pin = 0.0; + *hyst_state = X_RISING; + } + } + } + } + } + + + + if (ANALYSIS != MIF_AC) { /* DC & Transient Analyses */ + + OUTPUT(mc) = out; + PARTIAL(mc,mc) = pout_pin; + + } + else { /* AC Analysis */ + ac_gain.real = pout_pin; + ac_gain.imag= 0.0; + AC_GAIN(mc,mc) = ac_gain; + + } + } +} + diff --git a/src/xspice/icm/xtradev/core/core.h b/src/xspice/icm/xtradev/core/core.h new file mode 100644 index 000000000..4049e9648 --- /dev/null +++ b/src/xspice/icm/xtradev/core/core.h @@ -0,0 +1,38 @@ + + +/******************************************************/ +/****** Structures, etc. for core model. ******/ +/****** 10/24/91 JPM ******/ +/******************************************************/ + +/***** Value Definitions ******************************************/ + +#define HYST 1 +#define X_RISING TRUE +#define X_FALLING FALSE +#define PWL 1 +#define HYSTERESIS 2 + + + + + +/***** Define Error Messages **************************************/ + + + + + + +/***** Structure Definitions *************************************/ + + + + + + +/***** Function Definitions ***************************************/ + + + + diff --git a/src/xspice/icm/xtradev/core/ifspec.ifs b/src/xspice/icm/xtradev/core/ifspec.ifs new file mode 100644 index 000000000..05f9d4035 --- /dev/null +++ b/src/xspice/icm/xtradev/core/ifspec.ifs @@ -0,0 +1,144 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 27 Sept 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog core code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_core +Spice_Model_Name: core +Description: "magnetic core" + + +PORT_TABLE: + + +Port_Name: mc +Description: "magnetic core" +Direction: inout +Default_Type: gd +Allowed_Types: [g,gd] +Vector: no +Vector_Bounds: - +Null_Allowed: no + +PARAMETER_TABLE: + +Parameter_Name: H_array B_array +Description: "magnetic field array" "flux density array" +Data_Type: real real +Default_Value: - - +Limits: - - +Vector: yes yes +Vector_Bounds: [2 -] [2 -] +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: area length +Description: "cross-sectional area" "core length" +Data_Type: real real +Default_Value: - - +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: input_domain +Description: "input sm. domain" +Data_Type: real +Default_Value: 0.01 +Limits: [1e-12 0.5] +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: fraction +Description: "smoothing fractional/abs switch" +Data_Type: boolean +Default_Value: TRUE +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: mode +Description: "mode switch (1 = pwl, 2 = hyst)" +Data_Type: int +Default_Value: 1 +Limits: [1 2] +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: in_low in_high +Description: "input low value" "input high value" +Data_Type: real real +Default_Value: 0.0 1.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: hyst out_lower_limit +Description: "hysteresis" "output lower limit" +Data_Type: real real +Default_Value: 0.1 0.0 +Limits: [0 -] - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: out_upper_limit +Description: "output upper limit" +Data_Type: real +Default_Value: 1.0 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + + + + + + + + + + diff --git a/src/xspice/icm/xtradev/inductor/cfunc.mod b/src/xspice/icm/xtradev/inductor/cfunc.mod new file mode 100644 index 000000000..d848694f5 --- /dev/null +++ b/src/xspice/icm/xtradev/inductor/cfunc.mod @@ -0,0 +1,90 @@ +/* =========================================================================== +FILE cfunc.mod + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of an inductor code model + with current initial conditions. + +INTERFACES + + cm_inductor() + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +void *malloc(int); +void free(void *); + + +#define LI 0 + + +void cm_inductor (ARGS) +{ + Complex_t ac_gain; + double partial; + double ramp_factor; + double *li; + + /* Get the ramp factor from the .option ramptime */ + ramp_factor = cm_analog_ramp_factor(); + + /* Initialize/access instance specific storage for capacitor voltage */ + if(INIT) { + li = cm_analog_alloc(LI, sizeof(double)); + *li = PARAM(ic) * ramp_factor; + } + else { + li = cm_analog_get_ptr(LI, 0); + } + + /* Compute the output */ + if(ANALYSIS == DC) { + OUTPUT(ind) = PARAM(ic) * ramp_factor; + PARTIAL(ind, ind) = 0.0; + } + else if(ANALYSIS == AC) { + ac_gain.real = 0.0; + ac_gain.imag = 1.0 * RAD_FREQ * PARAM(l); + AC_GAIN(ind, ind) = ac_gain; + } + else if(ANALYSIS == TRANSIENT) { + if(ramp_factor < 1.0) { + *li = PARAM(ic) * ramp_factor; + OUTPUT(ind) = *li; + PARTIAL(ind, ind) = 0.0; + } + else { + cm_analog_integrate(INPUT(ind) / PARAM(l), li, &partial); + partial /= PARAM(l); + OUTPUT(ind) = *li; + PARTIAL(ind, ind) = partial; + } + } +} + diff --git a/src/xspice/icm/xtradev/inductor/ifspec.ifs b/src/xspice/icm/xtradev/inductor/ifspec.ifs new file mode 100644 index 000000000..e15732c8f --- /dev/null +++ b/src/xspice/icm/xtradev/inductor/ifspec.ifs @@ -0,0 +1,70 @@ +/* =========================================================================== +FILE ifspec.ifs + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of an inductor code model + with current initial conditions. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +NAME_TABLE: + +Spice_Model_Name: inductor +C_Function_Name: cm_inductor +Description: "Inductor with current initial condition" + + +PORT_TABLE: + +Port_Name: ind +Description: "inductor terminals" +Direction: inout +Default_Type: gd +Allowed_Types: [gd] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + +Parameter_Name: l ic +Description: "inductance" "current initial condition" +Data_Type: real real +Default_Value: - 0.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + diff --git a/src/xspice/icm/xtradev/lcouple/cfunc.mod b/src/xspice/icm/xtradev/lcouple/cfunc.mod new file mode 100644 index 000000000..0d91dfece --- /dev/null +++ b/src/xspice/icm/xtradev/lcouple/cfunc.mod @@ -0,0 +1,260 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE lcouple/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 13 Sep 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the lcouple code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_integrate() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_lcouple() + +AUTHORS + + 6 Jun 1991 Jeffrey P. Murray + +MODIFICATIONS + + 13 Sep 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the lcouple code model. + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void *cm_analog_alloc() + void *cm_analog_get_ptr() + int cm_analog_integrate() + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_LCOUPLE ROUTINE ===*/ + +/*********************************************** +* Note that this model incorporates a fake * +* integration in order to link in truncation * +* error checking...this may be removed at a * +* future date. JPM 9/13/91 * +***********************************************/ + + + +void cm_lcouple(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + double input_current, /* input current from electrical-side windings */ + output_voltage, /* output voltage reflected to electricaL-side */ + *output_voltage_fake, /* fake output voltage for use with + truncation error checking. */ + input_flux, /* input flux value from core side (represented + as a current. */ + output_mmf, /* output driving amp-turns to core side. */ + + num_turns, /* number of turns on inductor */ + pout_pin_fake, /* fake partial derivative of output + w.r.t. input (for use with integration */ + *in_flux, /* current input flux value from core side + (represented as a current). */ + *in_flux_old, /* previous timestep flux value */ + *in_flux_fake, /* fake input flux value for use with + truncation error checking. */ + delta; /* time delta from previous timepoint to + current value */ + + + Mif_Complex_t ac_gain; /* AC gain */ + + + + + /** Retrieve frequently used parameters... **/ + + num_turns = PARAM(num_turns); + + + + + + if (ANALYSIS != MIF_AC) { /**** DC & Transient Analyses ****/ + + /** Test for INIT; if so, allocate storage, otherwise, retrieve + previous timepoint input value... **/ + + if (INIT==1) { /* First pass...allocate storage for previous state. */ + /* Also, calculate roughly where the current output */ + /* will be and use this value to define current state. */ + + in_flux = cm_analog_alloc(1,sizeof(double)); + in_flux_old = cm_analog_get_ptr(1,1); + + /* assign fake input and output values for truncation + error checking */ + in_flux_fake = cm_analog_alloc(2,sizeof(double)); + output_voltage_fake = cm_analog_alloc(3,sizeof(double)); + + } + else { /* Allocation not necessary...retrieve previous values */ + + in_flux = cm_analog_get_ptr(TRUE,0); /* Set out pointer to current + time storage */ + in_flux_old = cm_analog_get_ptr(TRUE,1); /* Set old-output-state pointer + to previous time storage */ + + /* retrieve fake input and output values for truncation + error checking */ + in_flux_fake = cm_analog_get_ptr(2,0); + output_voltage_fake = cm_analog_get_ptr(3,0); + } + + + + + + /** Retrieve inputs... **/ + + input_current = INPUT(l); /* input from electrical side is a current */ + *in_flux = -INPUT(mmf_out); /* input from core side is a flux + represented as a current...note + that a negative is introduced, + because current INTO the positive + node would normally result in + a NEGATIVE output_voltage... + the minus sign corrects this. */ + + + /** Calculate output value for mmf... **/ + + output_mmf = num_turns * input_current; + + OUTPUT(mmf_out) = output_mmf; + PARTIAL(mmf_out,l) = num_turns; + + + + + + + /** Calculate output value for output_voltage... **/ + + if ( 0.0 == TIME ) { /*** Test to see if this is the first ***/ + /*** timepoint calculation...if ***/ + *in_flux_old = *in_flux; /*** so, return a zero d/dt value. ***/ + output_voltage = *output_voltage_fake = 0.0; + + OUTPUT(l) = output_voltage; + PARTIAL(l,mmf_out) = 0.0; + } + else { /*** Calculate value of d_dt.... ***/ + delta = TIME - T(1); + output_voltage = *output_voltage_fake = + num_turns * (*in_flux - *in_flux_old) / delta; + OUTPUT(l) = output_voltage; + PARTIAL(l,mmf_out) = -num_turns / delta; + + /* add fake cm_analog_integrate for truncation error checks */ + cm_analog_integrate(*output_voltage_fake,in_flux_fake,&pout_pin_fake); + + } + + } + + else { /**** AC Analysis...****/ + ac_gain.real = 0.0; + ac_gain.imag= num_turns * RAD_FREQ; + AC_GAIN(l,mmf_out) = ac_gain; + + ac_gain.real= num_turns; + ac_gain.imag= 0.0; + AC_GAIN(mmf_out,l) = ac_gain; + + } +} + + + + diff --git a/src/xspice/icm/xtradev/lcouple/ifspec.ifs b/src/xspice/icm/xtradev/lcouple/ifspec.ifs new file mode 100644 index 000000000..1a7e1eef5 --- /dev/null +++ b/src/xspice/icm/xtradev/lcouple/ifspec.ifs @@ -0,0 +1,54 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog lcouple code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_lcouple +Spice_Model_Name: lcouple +Description: "inductive coupling (for use with 'core' model)" + + +PORT_TABLE: + + +Port_Name: l mmf_out +Description: "inductor" "mmf output (in Ampere-turns)" +Direction: inout inout +Default_Type: hd hd +Allowed_Types: [h,hd] [hd] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + + +PARAMETER_TABLE: + + +Parameter_Name: num_turns +Description: "number of inductor turns" +Data_Type: real +Default_Value: 1.0 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + diff --git a/src/xspice/icm/xtradev/lmeter/cfunc.mod b/src/xspice/icm/xtradev/lmeter/cfunc.mod new file mode 100644 index 000000000..4f38e347b --- /dev/null +++ b/src/xspice/icm/xtradev/lmeter/cfunc.mod @@ -0,0 +1,133 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE lmeter/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 30 Jul 1991 Bill Kuhn + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the lmeter code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmeters.c double cm_netlist_get_l() + + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_lmeter() + +AUTHORS + + 30 Jul 1991 Bill Kuhn + + +MODIFICATIONS + + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the lmeter code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmeters.c double cm_netlist_get_l() + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_LMETER ROUTINE ===*/ + + +void cm_lmeter (ARGS) +{ + + double leq; + + if(INIT) { + leq = cm_netlist_get_l(); + STATIC_VAR(l) = leq; + } + else + leq = STATIC_VAR(l); + + OUTPUT(out) = PARAM(gain) * leq; +} + + + + diff --git a/src/xspice/icm/xtradev/lmeter/ifspec.ifs b/src/xspice/icm/xtradev/lmeter/ifspec.ifs new file mode 100644 index 000000000..3c6f1b2fa --- /dev/null +++ b/src/xspice/icm/xtradev/lmeter/ifspec.ifs @@ -0,0 +1,56 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 302 Jul 1991 Bill Kuhn + + +SUMMARY + + This file contains the interface specification file for the + analog lmeter code model. + +===============================================================================*/ + +NAME_TABLE: + +Spice_Model_Name: lmeter +C_Function_Name: cm_lmeter +Description: "ATESSE 1 compatible inductance meter" + + +PORT_TABLE: + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: v v +Allowed_Types: [v, vd] [v, vd, i, id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: gain +Description: "L to voltage conversion factor" +Data_Type: real +Default_Value: 1.0 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +STATIC_VAR_TABLE: + +Static_Var_Name: l +Data_Type: real +Description: "inductance connected to input node" + diff --git a/src/xspice/icm/xtradev/modpath.lst b/src/xspice/icm/xtradev/modpath.lst new file mode 100644 index 000000000..a07ee3372 --- /dev/null +++ b/src/xspice/icm/xtradev/modpath.lst @@ -0,0 +1,10 @@ +aswitch +capacitor +cmeter +core +inductor +lcouple +lmeter +potentiometer +zener + diff --git a/src/xspice/icm/xtradev/potentiometer/cfunc.mod b/src/xspice/icm/xtradev/potentiometer/cfunc.mod new file mode 100644 index 000000000..50e681371 --- /dev/null +++ b/src/xspice/icm/xtradev/potentiometer/cfunc.mod @@ -0,0 +1,222 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE potentiometer/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 19 June 1992 Jeffrey P. Murray + + +MODIFICATIONS + + 19 June 1992 Jeffrey P. Murray + + +SUMMARY + + This file contains the functional description of the potentiometer + code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + + + +/*============================================================================== + +FUNCTION cm_potentiometer() + +AUTHORS + + 19 June 1992 Jeffrey P. Murray + +MODIFICATIONS + + 19 June 1992 Jeffrey P. Murray + +SUMMARY + + This function implements the potentiometer code model. + +INTERFACES + + FILE ROUTINE CALLED + + CMmacros.h cm_message_send(); + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_POTENTIOMETER ROUTINE ===*/ + + +void cm_potentiometer (ARGS) +{ + double position; /* position of wiper contact */ + double resistance; /* total resistance */ + double r_lower; /* resistance from r0 to wiper */ + double r_upper; /* resistance from wiper to r1 */ + double vr0; /* voltage at r0 */ + double vr1; /* voltage at r1 */ + double vwiper; /* voltage at wiper */ + + + + Mif_Complex_t ac_gain; + + + + /* Retrieve frequently used parameters... */ + + position = PARAM(position); + resistance = PARAM(r); + + /* Retrieve input voltages... */ + vr0 = INPUT(r0); + vwiper = INPUT(wiper); + vr1 = INPUT(r1); + + + if ( PARAM(log) == FALSE ) { + + /* Linear Variation in resistance w.r.t. position */ + r_lower = position * resistance; + r_upper = resistance - r_lower; + + } + else { + + /* Logarithmic Variation in resistance w.r.t. position */ + r_lower = resistance / + pow(10.0,(position * PARAM(log_multiplier))); + r_upper = resistance - r_lower; + + } + + + + + + /* Output DC & Transient Values */ + + if(ANALYSIS != MIF_AC) { + OUTPUT(r0) = (vr0 - vwiper) / r_lower; + OUTPUT(r1) = (vr1 - vwiper) / r_upper; + OUTPUT(wiper) = ((vwiper - vr0)/r_lower) + ((vwiper - vr1)/r_upper); + + PARTIAL(r0,r0) = 1.0 / r_lower; + PARTIAL(r0,r1) = 0.0; + PARTIAL(r0,wiper) = -1.0 / r_lower; + + PARTIAL(r1,r0) = 0.0; + PARTIAL(r1,r1) = 1.0 / r_upper;; + PARTIAL(r1,wiper) = -1.0 / r_upper; + + PARTIAL(wiper,r0) = -1.0 / r_lower; + PARTIAL(wiper,r1) = -1.0 / r_upper; + PARTIAL(wiper,wiper) = (1.0/r_lower) + (1.0/r_upper); + + } + else { + + /* Output AC Gain Values */ + + ac_gain.imag= 0.0; + + ac_gain.real = -1.0 / r_lower; + AC_GAIN(r0,r0) = ac_gain; + + ac_gain.real = 0.0; + AC_GAIN(r0,r1) = ac_gain; + + ac_gain.real = 1.0 / r_lower; + AC_GAIN(r0,wiper) = ac_gain; + + ac_gain.real = 0.0; + AC_GAIN(r1,r0) = ac_gain; + + ac_gain.real = -1.0 / r_upper; + AC_GAIN(r1,r1) = ac_gain; + + ac_gain.real = 1.0 / r_upper; + AC_GAIN(r1,wiper) = ac_gain; + + ac_gain.real = 1.0 / r_lower; + AC_GAIN(wiper,r0) = ac_gain; + + ac_gain.real = 1.0 / r_upper; + AC_GAIN(wiper,r1) = ac_gain; + + ac_gain.real = -(1.0/r_lower) - (1.0/r_upper); + AC_GAIN(wiper,wiper) = ac_gain; + + } + +} + + + + diff --git a/src/xspice/icm/xtradev/potentiometer/ifspec.ifs b/src/xspice/icm/xtradev/potentiometer/ifspec.ifs new file mode 100644 index 000000000..0cb9f6ff2 --- /dev/null +++ b/src/xspice/icm/xtradev/potentiometer/ifspec.ifs @@ -0,0 +1,93 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 19 June 1992 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog potentiometer code model. + +===============================================================================*/ + +NAME_TABLE: + +Spice_Model_Name: potentiometer +C_Function_Name: cm_potentiometer +Description: "potentiometer" + + +PORT_TABLE: + +Port_Name: r0 wiper +Description: "pot connection 0" "wiper contact" +Direction: inout inout +Default_Type: g g +Allowed_Types: [g] [g] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PORT_TABLE: + +Port_Name: r1 +Description: "pot connection 1" +Direction: inout +Default_Type: g +Allowed_Types: [g] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + +Parameter_Name: position +Description: "position of wiper connection (0.0 to 1.0)" +Data_Type: real +Default_Value: 0.5 +Limits: [0.0 1.0] +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + +PARAMETER_TABLE: + +Parameter_Name: log r +Description: "log-linear switch" "total resistance" +Data_Type: boolean real +Default_Value: FALSE 1.0e5 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + +Parameter_Name: log_multiplier +Description: "multiplier constant for log resistance" +Data_Type: real +Default_Value: 1.0 +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + + +STATIC_VAR_TABLE: + +Static_Var_Name: +Data_Type: +Description: diff --git a/src/xspice/icm/xtradev/udnpath.lst b/src/xspice/icm/xtradev/udnpath.lst new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/src/xspice/icm/xtradev/udnpath.lst @@ -0,0 +1,2 @@ + + diff --git a/src/xspice/icm/xtradev/zener/cfunc.mod b/src/xspice/icm/xtradev/zener/cfunc.mod new file mode 100644 index 000000000..c414efee9 --- /dev/null +++ b/src/xspice/icm/xtradev/zener/cfunc.mod @@ -0,0 +1,355 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ + +FILE zener/cfunc.mod + +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +PROJECT A-8503-405 + + +AUTHORS + + 2 May 1991 Jeffrey P. Murray + + +MODIFICATIONS + + 18 Sep 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the model-specific routines used to + functionally describe the zener code model. + + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void cm_analog_not_converged() + + +REFERENCED FILES + + Inputs from and outputs to ARGS structure. + + +NON-STANDARD FEATURES + + NONE + +===============================================================================*/ + +/*=== INCLUDE FILES ====================*/ + +#include + + + +/*=== CONSTANTS ========================*/ + + + + +/*=== MACROS ===========================*/ + + + + +/*=== LOCAL VARIABLES & TYPEDEFS =======*/ + + + + +/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ + + + + + +/*============================================================================== + +FUNCTION void cm_zener() + +AUTHORS + + 2 May 1991 Jeffrey P. Murray + +MODIFICATIONS + + 18 Sep 1991 Jeffrey P. Murray + 2 Oct 1991 Jeffrey P. Murray + +SUMMARY + + This function implements the zener code model. + +INTERFACES + + FILE ROUTINE CALLED + + CM.c void cm_analog_not_converged() + + +RETURNED VALUE + + Returns inputs and outputs via ARGS structure. + +GLOBAL VARIABLES + + NONE + +NON-STANDARD FEATURES + + NONE + +==============================================================================*/ + +/*=== CM_ZENER ROUTINE ===*/ + + +void cm_zener(ARGS) /* structure holding parms, + inputs, outputs, etc. */ +{ + double v_breakdown, /* breakdown voltage parameter */ + i_breakdown, /* breakdown current parameter */ + r_breakdown, /* breakdown resistance parameter */ + i_rev, /* reverse current parameter */ + i_sat, /* saturation current parameter... + a.k.a. Io in the forward diode + characteristic equation...see below. */ + n_forward, /* forward emission coefficient parameter... + a.k.a. "n" in the forward diode + characteristic equation...see below. */ + vt, /* volt-equivalent of temperature, Vt, + used in conjunction with n = n_forward + value to describe the forward-voltage + diode behavior described as: + + I = Io * (e^(V/n*Vt) - 1.0) */ + + v_1_2, /* Boundary value voltage between region + 1 (forward diode characteristic) and + region 2 (linear region) */ + k, /* intermediate value used to find v_2_3 */ + v_2_3, /* Boundary value voltage between region + 2 (linear region) and region 3 + (reverse breakdown region) */ + slope1, /* Slope of endpoint for a two segment model */ + slope2, /* Slope of endpoint for a two segment model */ + temp, /* temporary variable used to calulate the + derivatives */ + v_zener, /* input voltage across zener */ + i_zener, /* current which is allowed to + flow through zener, for a given voltage */ + i0, + v0, + a, /* coefficient used to calculate "c" */ + b, /* coefficient used to calculate "c" */ + c, /* A constant to match ordinates at + region 2/3 boundary */ + deriv, /* partial derivative of the output + current w.r.t. the input voltage */ + diff, /* difference between slope1 and slope2 */ + ord_1_2, /* Compute ordinate at boundary of regions 1 & 2 */ + *previous_voltage, /* Previous voltage value (used for limiting) */ + increment, /* Increment value calculated from the + previous_input for v_zener input limiting */ + g; /* conductance value equal to + i_rev / v_breakdown. This value is + used to simulate a reverse-leakage + conductance in parallel with the + zener characteristic. */ + + Mif_Complex_t ac_gain; /* AC gain */ + + + if (INIT==1) { /* First pass...allocate storage for previous value... */ + + /* Allocate storage for frequencies */ + STATIC_VAR(previous_voltage) = (double *) malloc(sizeof(double)); + previous_voltage = STATIC_VAR(previous_voltage); + + /* Set previous_voltage value to zero... */ + *previous_voltage = 0.0; + + } + else { + + previous_voltage = STATIC_VAR(previous_voltage); + + } + + + /* Retrieve frequently used parameters & inputs... */ + + v_breakdown = PARAM(v_breakdown); + i_breakdown = PARAM(i_breakdown); + r_breakdown = PARAM(r_breakdown); + i_rev = PARAM(i_rev); + i_sat = PARAM(i_sat); + n_forward = PARAM(n_forward); + + v_zener = INPUT(z); + + + + + /** If the limit_switch parameter is set, test the **/ + /** current input against previous value for limiting **/ + + if ( MIF_TRUE == PARAM(limit_switch) ) { + /* Check magnitude of v_zener */ + if ( fabs(*previous_voltage) >= 1.0 ) { + increment = 0.1 * *previous_voltage; + } + else { + if (v_zener < 0.0) { + increment = -0.1; + } + else { + increment = 0.1; + } + } + + /* Test v_zener for reasonable change in value since last call.. */ + if ( fabs(v_zener) > ( fabs(*previous_voltage + increment) ) ) { + + /* Apply limiting... */ + *previous_voltage = v_zener = *previous_voltage + increment; + + cm_analog_not_converged(); + + } + else { + + *previous_voltage = v_zener; + + } + } + + + + + + /* Compute voltage at boundary of regions 1 & 2 */ + + vt = 0.026; + v_1_2 = n_forward * vt * log(n_forward * vt / 10.0); + + + /* Compute voltage at boundary of regions 2 & 3 */ + + k = 1.0 / i_breakdown / r_breakdown; + v_2_3 = -v_breakdown + log(10.0/i_sat/r_breakdown)/k; + + + + /* Compare v_1_2 and v_2_3 to determine if a 3 segment model is possible */ + + if (v_2_3 < v_1_2) { /* Use a 3 segment model */ + + /* Compute v0 for region 3... */ + + i0 = 1.e-6; + v0 = -v_breakdown + 1.0/k*log(i_breakdown/i0); + + + /* Compute ordinate at boundary of regions 1 & 2 */ + + ord_1_2 = i_sat * (exp(v_1_2/n_forward/vt) - 1.0); + + + /* Compute a & b coefficients for linear section in region 2 */ + + a = i_sat / 10.0; + b = ord_1_2 - a * v_1_2; + + + /* Compute constant to match ordinates at region 2/3 boundary */ + + c = a*v_2_3 + b + i0*exp(-k * (v_2_3 - v0)); + + + /* Compute zener current */ + + if (v_zener >= v_1_2) { + temp = exp(v_zener / n_forward / vt); + i_zener = i_sat * (temp - 1.0); + deriv = i_sat / n_forward / vt * temp; + } + else { + if (v_zener >= v_2_3) { + i_zener = a * v_zener + b; + deriv = i_sat / 10.0; + } + else { + temp = exp(-k * (v_zener - v0)); + i_zener = -i0 * temp + c; + deriv = k * i0 * temp; + } + } + } + else { /* Must use a 2 segment model */ + + /* Determine i0 for reverse region */ + + i0 = i_breakdown / (exp(k * v_breakdown) - 1.0); + + + /* Determine the slopes at the region endpoints */ + + slope1 = i_sat / n_forward / vt; + slope2 = i0 * k; + + + /* Determine zener current & first partial... */ + /* Use a linear conductance in one region to match */ + /* slopes at the boundary. */ + + if (v_zener >= 0.0) { + temp = exp(v_zener / n_forward / vt); + i_zener = i_sat * (temp - 1.0); + deriv = i_sat / n_forward / vt * temp; + diff = slope2 - slope1; + if (diff > 0.0) { + i_zener = i_zener + diff * v_zener; + deriv = deriv + diff; + } + } + else { + temp = exp(-k * v_zener); + i_zener = -i0 * (temp - 1.0); + deriv = k * i0 * temp; + diff = slope1 - slope2; + if (diff > 0.0) { + i_zener = i_zener + diff * v_zener; + deriv = deriv + diff; + } + } + } + + /* Add resistor in parallel to simulate reverse leakage */ + + g = i_rev / v_breakdown; + i_zener = i_zener + g * v_zener; + deriv = deriv + g; + + + if(ANALYSIS != MIF_AC) { /* Output DC & Transient Values */ + OUTPUT(z) = i_zener; + PARTIAL(z,z) = deriv; + } + else { /* Output AC Gain */ + ac_gain.real = deriv; + ac_gain.imag= 0.0; + AC_GAIN(z,z) = ac_gain; + } +} + diff --git a/src/xspice/icm/xtradev/zener/ifspec.ifs b/src/xspice/icm/xtradev/zener/ifspec.ifs new file mode 100644 index 000000000..2795422d1 --- /dev/null +++ b/src/xspice/icm/xtradev/zener/ifspec.ifs @@ -0,0 +1,97 @@ +/* $Id$ */ +/*.......1.........2.........3.........4.........5.........6.........7.........8 +================================================================================ +Copyright 1991 +Georgia Tech Research Corporation, Atlanta, Ga. 30332 +All Rights Reserved + +AUTHORS + + 2 May 1991 Jeffrey P. Murray + + +SUMMARY + + This file contains the interface specification file for the + analog zener code model. + +===============================================================================*/ + +NAME_TABLE: + + +C_Function_Name: cm_zener +Spice_Model_Name: zener +Description: "zener diode" + + +PORT_TABLE: + + +Port_Name: z +Description: "zener" +Direction: inout +Default_Type: gd +Allowed_Types: [gd] +Vector: no +Vector_Bounds: - +Null_Allowed: no + + +PARAMETER_TABLE: + + +Parameter_Name: v_breakdown i_breakdown +Description: "breakdown voltage" "breakdown current" +Data_Type: real real +Default_Value: - 2e-2 +Limits: [1e-6 1e6] [1e-9 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no yes + + +PARAMETER_TABLE: + + +Parameter_Name: r_breakdown i_rev +Description: "breakdown resistance" "reverse current" +Data_Type: real real +Default_Value: 1.0 1e-6 +Limits: [1e-12 -] [1e-9 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + + +PARAMETER_TABLE: + +Parameter_Name: i_sat n_forward +Description: "saturation current" "forward emission co" +Data_Type: real real +Default_Value: 1e-12 1.0 +Limits: [1e-15 -] [.1 10] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + +PARAMETER_TABLE: + +Parameter_Name: limit_switch +Description: "switch for on-board limiting (convergence aid)" +Data_Type: boolean +Default_Value: FALSE +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + + +STATIC_VAR_TABLE: + +Static_Var_Name: previous_voltage +Data_Type: pointer +Description: "iteration holding variable for limiting" diff --git a/src/xspice/icm/xtraevt/d_to_real/cfunc.mod b/src/xspice/icm/xtraevt/d_to_real/cfunc.mod new file mode 100644 index 000000000..dbea11f45 --- /dev/null +++ b/src/xspice/icm/xtraevt/d_to_real/cfunc.mod @@ -0,0 +1,43 @@ +/* $Id$ */ + +void ucm_d_to_real (ARGS) +{ + + Digital_State_t in; + + double *out; + double delay; + double zero; + double one; + double ena; + + + in = INPUT_STATE(in); + if(PORT_NULL(enable)) + ena = 1.0; + else if(INPUT_STATE(enable) == ONE) + ena = 1.0; + else + ena = 0.0; + out = OUTPUT(out); + + zero = PARAM(zero); + one = PARAM(one); + delay = PARAM(delay); + + + if(in == ZERO) + *out = zero * ena; + else if(in == UNKNOWN) + *out = (zero + one) / 2.0 * ena; + else + *out = one * ena; + + if(TIME > 0.0) + OUTPUT_DELAY(out) = delay; + +} + + + + diff --git a/src/xspice/icm/xtraevt/d_to_real/ifspec.ifs b/src/xspice/icm/xtraevt/d_to_real/ifspec.ifs new file mode 100644 index 000000000..29369a966 --- /dev/null +++ b/src/xspice/icm/xtraevt/d_to_real/ifspec.ifs @@ -0,0 +1,32 @@ +/* $Id$ */ + +NAME_TABLE: + +Spice_Model_Name: d_to_real +C_Function_Name: ucm_d_to_real +Description: "Node bridge from digital to real with enable" + + +PORT_TABLE: + +Port_Name: in enable out +Description: "input" "enable" "output" +Direction: in in out +Default_Type: d d real +Allowed_Types: [d] [d] [real] +Vector: no no no +Vector_Bounds: - - - +Null_Allowed: no yes no + + +PARAMETER_TABLE: + +Parameter_Name: zero one delay +Description: "value for 0" "value for 1" "delay" +Data_Type: real real real +Default_Value: 0.0 1.0 1e-9 +Limits: - - [1e-15 -] +Vector: no no no +Vector_Bounds: - - - +Null_Allowed: yes yes yes + diff --git a/src/xspice/icm/xtraevt/int/udnfunc.c b/src/xspice/icm/xtraevt/int/udnfunc.c new file mode 100644 index 000000000..bf7868b02 --- /dev/null +++ b/src/xspice/icm/xtraevt/int/udnfunc.c @@ -0,0 +1,190 @@ +/*============================================================================ +FILE int/udnfunc.c + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of the 'int' node type + used by event-driven models that simulate with integer type data. + These functions are called exclusively through function + pointers in an Evt_Udn_Info_t data structure. + +INTERFACES + + Evt_Udn_Info_t udn_int_info + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +============================================================================*/ + +#include +#include "cm.h" + +#include "evtudn.h" + +void *tmalloc(unsigned); + + + +/* ************************************************************************ */ + +void udn_int_create(CREATE_ARGS) +{ + /* Malloc space for an int */ + MALLOCED_PTR = tmalloc(sizeof(int)); +} + + +/* ************************************************************************ */ + +void udn_int_dismantle(DISMANTLE_ARGS) +{ + /* Do nothing. There are no internally malloc'ed things to dismantle */ +} + + +/* ************************************************************************ */ + +void udn_int_initialize(INITIALIZE_ARGS) +{ + int *int_struct = STRUCT_PTR; + + + /* Initialize to zero */ + *int_struct = 0; +} + + +/* ************************************************************************ */ + +void udn_int_invert(INVERT_ARGS) +{ + int *int_struct = STRUCT_PTR; + + + /* Invert the state */ + *int_struct = -(*int_struct); +} + + +/* ************************************************************************ */ + +void udn_int_copy(COPY_ARGS) +{ + int *int_from_struct = INPUT_STRUCT_PTR; + int *int_to_struct = OUTPUT_STRUCT_PTR; + + /* Copy the structure */ + *int_to_struct = *int_from_struct; +} + +/* ************************************************************************ */ + +void udn_int_resolve(RESOLVE_ARGS) +{ + int **array = INPUT_STRUCT_PTR_ARRAY; + int *out = OUTPUT_STRUCT_PTR; + int num_struct = INPUT_STRUCT_PTR_ARRAY_SIZE; + + int sum; + int i; + + /* Sum the values */ + for(i = 0, sum = 0; i < num_struct; i++) + sum += *(array[i]); + + /* Assign the result */ + *out = sum; +} + +/* ************************************************************************ */ + +void udn_int_compare(COMPARE_ARGS) +{ + int *int_struct1 = STRUCT_PTR_1; + int *int_struct2 = STRUCT_PTR_2; + + /* Compare the structures */ + if((*int_struct1) == (*int_struct2)) + EQUAL = TRUE; + else + EQUAL = FALSE; +} + + +/* ************************************************************************ */ + +void udn_int_plot_val(PLOT_VAL_ARGS) +{ + int *int_struct = STRUCT_PTR; + + /* Output a value for the int struct */ + PLOT_VAL = *int_struct; +} + + +/* ************************************************************************ */ + +void udn_int_print_val(PRINT_VAL_ARGS) +{ + int *int_struct = STRUCT_PTR; + + /* Allocate space for the printed value */ + PRINT_VAL = tmalloc(30); + + /* Print the value into the string */ + sprintf(PRINT_VAL, "%8d", *int_struct); +} + + + +/* ************************************************************************ */ + +void udn_int_ipc_val(IPC_VAL_ARGS) +{ + /* Simply return the structure and its size */ + IPC_VAL = STRUCT_PTR; + IPC_VAL_SIZE = sizeof(int); +} + + + +Evt_Udn_Info_t udn_int_info = { + + "int", + "integer valued data", + + udn_int_create, + udn_int_dismantle, + udn_int_initialize, + udn_int_invert, + udn_int_copy, + udn_int_resolve, + udn_int_compare, + udn_int_plot_val, + udn_int_print_val, + udn_int_ipc_val + +}; diff --git a/src/xspice/icm/xtraevt/modpath.lst b/src/xspice/icm/xtraevt/modpath.lst new file mode 100644 index 000000000..304d32f95 --- /dev/null +++ b/src/xspice/icm/xtraevt/modpath.lst @@ -0,0 +1,6 @@ +d_to_real +real_delay +real_gain +real_to_v + + diff --git a/src/xspice/icm/xtraevt/real/udnfunc.c b/src/xspice/icm/xtraevt/real/udnfunc.c new file mode 100644 index 000000000..57fad9e46 --- /dev/null +++ b/src/xspice/icm/xtraevt/real/udnfunc.c @@ -0,0 +1,194 @@ +/*============================================================================ +FILE real/udnfunc.c + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of the 'real' node type + used by event-driven models that simulate with real type data. + These functions are called exclusively through function + pointers in an Evt_Udn_Info_t data structure. + +INTERFACES + + Evt_Udn_Info_t udn_real_info + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +============================================================================*/ + +#include +#include "cm.h" + +#include "evtudn.h" + +void *tmalloc(unsigned); + + + +/* ************************************************************************ */ + +void udn_real_create(CREATE_ARGS) +{ + /* Malloc space for a real struct */ + MALLOCED_PTR = tmalloc(sizeof(double)); +} + + +/* ************************************************************************ */ + +void udn_real_dismantle(DISMANTLE_ARGS) +{ + /* Do nothing. There are no internally malloc'ed things to dismantle */ +} + + +/* ************************************************************************ */ + +void udn_real_initialize(INITIALIZE_ARGS) +{ + double *real_struct = STRUCT_PTR; + + + /* Initialize to zero */ + *real_struct = 0.0; +} + + +/* ************************************************************************ */ + +void udn_real_invert(INVERT_ARGS) +{ + double *real_struct = STRUCT_PTR; + + + /* Invert the state */ + *real_struct = -(*real_struct); +} + + +/* ************************************************************************ */ + +void udn_real_resolve(RESOLVE_ARGS) +{ + double **array = INPUT_STRUCT_PTR_ARRAY; + double *out = OUTPUT_STRUCT_PTR; + int num_struct = INPUT_STRUCT_PTR_ARRAY_SIZE; + + double sum; + int i; + + /* Sum the values */ + for(i = 0, sum = 0.0; i < num_struct; i++) + sum += *(array[i]); + + /* Assign the result */ + *out = sum; +} + +/* ************************************************************************ */ + +void udn_real_copy(COPY_ARGS) +{ + double *real_from_struct = INPUT_STRUCT_PTR; + double *real_to_struct = OUTPUT_STRUCT_PTR; + + /* Copy the structure */ + *real_to_struct = *real_from_struct; +} + + +/* ************************************************************************ */ + +void udn_real_compare(COMPARE_ARGS) +{ + double *real_struct1 = STRUCT_PTR_1; + double *real_struct2 = STRUCT_PTR_2; + + /* Compare the structures */ + if((*real_struct1) == (*real_struct2)) + EQUAL = TRUE; + else + EQUAL = FALSE; +} + + +/* ************************************************************************ */ + +void udn_real_plot_val(PLOT_VAL_ARGS) +{ + double *real_struct = STRUCT_PTR; + + + /* Output a value for the real struct */ + PLOT_VAL = *real_struct; +} + + +/* ************************************************************************ */ + +void udn_real_print_val(PRINT_VAL_ARGS) +{ + double *real_struct = STRUCT_PTR; + + + /* Allocate space for the printed value */ + PRINT_VAL = tmalloc(30); + + /* Print the value into the string */ + sprintf(PRINT_VAL, "%15.6e", *real_struct); +} + + + +/* ************************************************************************ */ + +void udn_real_ipc_val(IPC_VAL_ARGS) +{ + /* Simply return the structure and its size */ + IPC_VAL = STRUCT_PTR; + IPC_VAL_SIZE = sizeof(double); +} + + + +Evt_Udn_Info_t udn_real_info = { + + "real", + "real valued data", + + udn_real_create, + udn_real_dismantle, + udn_real_initialize, + udn_real_invert, + udn_real_copy, + udn_real_resolve, + udn_real_compare, + udn_real_plot_val, + udn_real_print_val, + udn_real_ipc_val + +}; + diff --git a/src/xspice/icm/xtraevt/real_delay/cfunc.mod b/src/xspice/icm/xtraevt/real_delay/cfunc.mod new file mode 100644 index 000000000..7ac66821c --- /dev/null +++ b/src/xspice/icm/xtraevt/real_delay/cfunc.mod @@ -0,0 +1,46 @@ +/* $Id$ */ + + +#define CLK_STATE 0 + + +void ucm_real_delay (ARGS) +{ + + double *in; + double *out; + + Digital_State_t *state; + Digital_State_t *old_state; + + + if(INIT) { + state = (void *) cm_event_alloc(CLK_STATE, sizeof(Digital_State_t)); + old_state = state; + *state = INPUT_STATE(clk); + } + else { + state = (void *) cm_event_get_ptr(CLK_STATE, 0); + old_state = (void *) cm_event_get_ptr(CLK_STATE, 1); + } + + if(ANALYSIS != TRANSIENT) + OUTPUT_CHANGED(out) = FALSE; + else { + *state = INPUT_STATE(clk); + if(*state == *old_state) + OUTPUT_CHANGED(out) = FALSE; + else if(*state != ONE) + OUTPUT_CHANGED(out) = FALSE; + else { + in = INPUT(in); + out = OUTPUT(out); + *out = *in; + OUTPUT_DELAY(out) = PARAM(delay); + } + } +} + + + + diff --git a/src/xspice/icm/xtraevt/real_delay/ifspec.ifs b/src/xspice/icm/xtraevt/real_delay/ifspec.ifs new file mode 100644 index 000000000..20c6413ca --- /dev/null +++ b/src/xspice/icm/xtraevt/real_delay/ifspec.ifs @@ -0,0 +1,33 @@ +/* $Id$ */ + +NAME_TABLE: + +Spice_Model_Name: real_delay +C_Function_Name: ucm_real_delay +Description: "A Z ** -1 block working on real data" + + +PORT_TABLE: + +Port_Name: in clk out +Description: "input" "clock" "output" +Direction: in in out +Default_Type: real d real +Allowed_Types: [real] [d] [real] +Vector: no no no +Vector_Bounds: - - - +Null_Allowed: no no no + + +PARAMETER_TABLE: + +Parameter_Name: delay +Description: "delay from clk to out" +Data_Type: real +Default_Value: 1e-9 +Limits: [1e-15 -] +Vector: no +Vector_Bounds: - +Null_Allowed: yes + + diff --git a/src/xspice/icm/xtraevt/real_gain/cfunc.mod b/src/xspice/icm/xtraevt/real_gain/cfunc.mod new file mode 100644 index 000000000..7d6285097 --- /dev/null +++ b/src/xspice/icm/xtraevt/real_gain/cfunc.mod @@ -0,0 +1,39 @@ +/* $Id$ */ + +void ucm_real_gain (ARGS) +{ + double *in; + double *out; + + double in_offset; + double gain; + double out_offset; + double delay; + double ic; + + + /* Get the input and output pointers */ + in = INPUT(in); + out = OUTPUT(out); + + /* Get the parameters */ + in_offset = PARAM(in_offset); + gain = PARAM(gain); + out_offset = PARAM(out_offset); + delay = PARAM(delay); + ic = PARAM(ic); + + + /* Assign the output and delay */ + if(ANALYSIS == DC) { + *out = ic; + if(INIT) + cm_event_queue(delay); + } + else { + *out = gain * (*in + in_offset) + out_offset; + OUTPUT_DELAY(out) = delay; + } +} + + diff --git a/src/xspice/icm/xtraevt/real_gain/ifspec.ifs b/src/xspice/icm/xtraevt/real_gain/ifspec.ifs new file mode 100644 index 000000000..b6a8005a9 --- /dev/null +++ b/src/xspice/icm/xtraevt/real_gain/ifspec.ifs @@ -0,0 +1,45 @@ +/* $Id$ */ + +NAME_TABLE: + +Spice_Model_Name: real_gain +C_Function_Name: ucm_real_gain +Description: "A gain block for event-driven real data" + + +PORT_TABLE: + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: real real +Allowed_Types: [real] [real] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: in_offset gain out_offset +Description: "input offset" "gain" "output offset" +Data_Type: real real real +Default_Value: 0.0 1.0 0.0 +Limits: - - - +Vector: no no no +Vector_Bounds: - - - +Null_Allowed: yes yes yes + + +PARAMETER_TABLE: + +Parameter_Name: delay ic +Description: "delay" "initial condition" +Data_Type: real real +Default_Value: 1.0e-9 0.0 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + diff --git a/src/xspice/icm/xtraevt/real_to_v/cfunc.mod b/src/xspice/icm/xtraevt/real_to_v/cfunc.mod new file mode 100644 index 000000000..3b5e08126 --- /dev/null +++ b/src/xspice/icm/xtraevt/real_to_v/cfunc.mod @@ -0,0 +1,75 @@ +/* $Id$ */ + + +#define TS 0 +#define VS 1 + + +void ucm_real_to_v (ARGS) +{ + + double *t, *v; + double *in; + + double out; + + + in = INPUT(in); + + if(INIT) { + t = (void *) cm_event_alloc(TS, 2 * sizeof(double)); + v = (void *) cm_event_alloc(VS, 2 * sizeof(double)); + t[0] = -2.0; + t[1] = -1.0; + v[0] = *in; + v[1] = *in; + } + else { + t = (void *) cm_event_get_ptr(TS, 0); + v = (void *) cm_event_get_ptr(VS, 0); + } + + switch(CALL_TYPE) { + + case ANALOG: + if(TIME == 0.0) { + OUTPUT(out) = *in; + v[0] = *in; + v[1] = *in; + } + else { + if(TIME <= t[0]) + OUTPUT(out) = v[0]; + else if(TIME >= t[1]) + OUTPUT(out) = v[1]; + else { + OUTPUT(out) = v[0] + (v[1] - v[0]) * + (TIME - t[0]) / (t[1] - t[0]); + } + } + break; + + case EVENT: + if(TIME == 0.0) + return; + if(TIME >= t[1]) { + v[0] = v[1]; + v[1] = *in; + t[0] = TIME; + t[1] = TIME + PARAM(transition_time); + } + else { + v[0] = v[0] + (v[1] - v[0]) * + (TIME - t[0]) / (t[1] - t[0]); + v[1] = *in; + t[0] = TIME; + t[1] = TIME + PARAM(transition_time); + } + break; + + } +} + + + + diff --git a/src/xspice/icm/xtraevt/real_to_v/ifspec.ifs b/src/xspice/icm/xtraevt/real_to_v/ifspec.ifs new file mode 100644 index 000000000..5d7b3d0e1 --- /dev/null +++ b/src/xspice/icm/xtraevt/real_to_v/ifspec.ifs @@ -0,0 +1,33 @@ +/* $Id$ */ + +NAME_TABLE: + +Spice_Model_Name: real_to_v +C_Function_Name: ucm_real_to_v +Description: "Node bridge from real to analog voltage" + + +PORT_TABLE: + +Port_Name: in out +Description: "input" "output" +Direction: in out +Default_Type: real v +Allowed_Types: [real] [v, vd, i, id] +Vector: no no +Vector_Bounds: - - +Null_Allowed: no no + + +PARAMETER_TABLE: + +Parameter_Name: gain transition_time +Description: "gain" "output transition time" +Data_Type: real real +Default_Value: 1.0 1e-9 +Limits: - [1e-15 -] +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes + + diff --git a/src/xspice/icm/xtraevt/udnpath.lst b/src/xspice/icm/xtraevt/udnpath.lst new file mode 100644 index 000000000..e1586dfaa --- /dev/null +++ b/src/xspice/icm/xtraevt/udnpath.lst @@ -0,0 +1,3 @@ +int +real +