add ideal balun device

This commit is contained in:
Florian Ballenegger 2020-09-15 18:18:13 +02:00
parent c49cb51492
commit 41c4098227
22 changed files with 818 additions and 7 deletions

View File

@ -1261,6 +1261,7 @@ AC_CONFIG_FILES([Makefile
src/spicelib/devices/numd/Makefile
src/spicelib/devices/numd2/Makefile
src/spicelib/devices/numos/Makefile
src/spicelib/devices/balun/Makefile
src/spicelib/parser/Makefile
src/ciderlib/Makefile
src/ciderlib/input/Makefile

View File

@ -0,0 +1,32 @@
* simple differential pair with simple common-mode feedback
.model n1 nmos level=49 version=3.3.0 tox=3.5n nch=2.4e17 nsub=5e16 vth0=0.6
.model p1 pmos level=49 version=3.3.0 tox=3.5n nch=2.5e17 nsub=5e16 vth0=-0.7
.subckt diffpair inp inn outp outn setcm vdd vss
Mp1 outp cmfb vdd vdd p1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=4
Mp2 outn cmfb vdd vdd p1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=4
Mpcm cmfb cmfb vdd vdd p1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=2
Mncm cmfb setcm tail vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=4
Mn1 outn inp tail vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=8
Mn2 outp inn tail vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=8
*bias
Mn0 tail bn vss vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=4
Mnn bn bn vss vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=4
Ib vss bn 1u
.ends
Xdiff inp inn outp outn setcm vdd vss diffpair
Cload outp outn 100f
Balun1#balun outp outn outcm outdiff
Balun1#balun inn inp incm indiff
Vprobediff outdiff indiff DC 0
Vprobecm outcm incm DC 0
Vset setcm vss DC 1.1
Vvdd vdd vss DC 3.3
Vvss vss 0 DC 0

View File

@ -134,6 +134,10 @@ if NDEV_WANTED
ngspice_LDADD += spicelib/devices/ndev/libndev.la
endif
if LOOPANA_WANTED
ngspice_LDADD += spicelib/devices/balun/libbalun.la
endif
if NUMDEV_WANTED
ngspice_LDADD += \
spicelib/devices/nbjt/libnbjt.la \
@ -413,6 +417,10 @@ libspice_la_LIBADD += \
spicelib/devices/ndev/libndev.la
endif
if LOOPANA_WANTED
libspice_la_LIBADD += spicelib/devices/balun/libbalun.la
endif
if NUMDEV_WANTED
libspice_la_LIBADD += \
spicelib/devices/nbjt/libnbjt.la \
@ -528,6 +536,10 @@ libngspice_la_LIBADD += \
spicelib/devices/ndev/libndev.la
endif
if LOOPANA_WANTED
libngspice_la_LIBADD += spicelib/devices/balun/libbalun.la
endif
if NUMDEV_WANTED
libngspice_la_LIBADD += \
spicelib/devices/nbjt/libnbjt.la \

View File

@ -51,6 +51,10 @@ Author: 1985 Wayne A. Christopher
/* gtri - end - 12/12/90 */
#endif
#ifdef WITH_LOOPANA
int INP2gentype(char* line);
#endif
/* SJB - Uncomment this line for debug tracing */
/*#define TRACE*/
@ -4701,6 +4705,11 @@ static void inp_compat(struct card *card)
if (*curr_line == '*')
continue;
#ifdef WITH_LOOPANA
if (INP2gentype(curr_line))
continue;
#endif
if (*curr_line == 'e') {
/* Exxx n1 n2 VCVS n3 n4 gain --> Exxx n1 n2 n3 n4 gain
@ -5771,6 +5780,10 @@ static void inp_bsource_compat(struct card *card)
else if (skip_control > 0) {
continue;
}
#ifdef WITH_LOOPANA
else if (INP2gentype(curr_line))
continue;
#endif
if (*curr_line == 'b') {
/* remove white spaces of everything inside {}*/
@ -8297,7 +8310,7 @@ static void inp_check_syntax(struct card *deck)
}
else {
if (!check_ch) {
fprintf(stderr, "Warning: Unusal leading characters like '%c' or others out of '= [] ? () & %\"!:,'\n", *cut_line);
fprintf(stderr, "Warning: Unusal leading characters like '%c' or others out of '= [] ? () & %%\"!:,'\n", *cut_line);
fprintf(stderr, " in netlist or included files, will be replaced with '*'\n");
check_ch = 1; /* just one warning */
}

View File

@ -61,6 +61,11 @@ if NUMDEV_WANTED
SUBDIRS += nbjt nbjt2 numd numd2 numos
endif
if LOOPANA_WANTED
SUBDIRS += balun
endif
DIST_SUBDIRS = \
asrc \
bjt \
@ -117,7 +122,8 @@ DIST_SUBDIRS = \
nbjt2 \
numd \
numd2 \
numos
numos \
balun
noinst_LTLIBRARIES = libdev.la

View File

@ -0,0 +1,22 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = libbalun.la
libbalun_la_SOURCES = \
balun.c \
balunask.c \
balundefs.h \
balunext.h \
baluninit.c \
baluninit.h \
balunitf.h \
balunload.c \
balunpar.c \
balunpzld.c \
balunset.c
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
AM_CFLAGS = $(STATIC)
MAINTAINERCLEANFILES = Makefile.in

View File

@ -0,0 +1,31 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1987 Thomas L. Quarles
**********/
#include "ngspice/ngspice.h"
#include "ngspice/ifsim.h"
#include "ngspice/devdefs.h"
#include "balundefs.h"
#include "ngspice/suffix.h"
IFparm BALUNpTable[] = { /* parameters */
OPU("pos_node", BALUN_POS_NODE, IF_INTEGER, "Positive node"),
OPU("neg_node", BALUN_NEG_NODE, IF_INTEGER, "Negative node"),
OPU("cm_node", BALUN_CM_NODE, IF_INTEGER, "Common-mode node"),
OPU("diff_node", BALUN_DIFF_NODE, IF_INTEGER, "Differential node"),
OP("p", BALUN_POWER, IF_REAL, "Power"),
};
char *BALUNnames[] = {
"Pos",
"Neg",
"CM",
"Diff"
};
int BALUNnSize = NUMELEMS(BALUNnames);
int BALUNpTSize = NUMELEMS(BALUNpTable);
int BALUNmPTSize = 0;
int BALUNiSize = sizeof(BALUNinstance);
int BALUNmSize = sizeof(BALUNmodel);

View File

@ -0,0 +1,63 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1987 Thomas L. Quarles
**********/
/*
* This routine gives access to the internal device parameters
* of Voltage Controlled Voltage Source
*/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "ngspice/devdefs.h"
#include "ngspice/ifsim.h"
#include "balundefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/* ARGSUSED */
int
BALUNask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *select)
{
BALUNinstance *here = (BALUNinstance *)inst;
static char *msg = "Power not available for ac analysis";
switch(which) {
case BALUN_POS_NODE:
value->iValue = here->BALUNposNode;
return (OK);
case BALUN_NEG_NODE:
value->iValue = here->BALUNnegNode;
return (OK);
case BALUN_DIFF_NODE:
value->iValue = here->BALUNdiffNode;
return (OK);
case BALUN_CM_NODE:
value->iValue = here->BALUNcmNode;
return (OK);
case BALUN_BRPOS:
value->iValue = here->BALUNbranchpos;
return (OK);
case BALUN_BRNEG:
value->iValue = here->BALUNbranchneg;
return (OK);
case BALUN_POWER :
if (ckt->CKTcurrentAnalysis & DOING_AC) {
errMsg = TMALLOC(char, strlen(msg) + 1);
errRtn = "BALUNask";
strcpy(errMsg,msg);
return(E_ASKPOWER);
} else {
value->rValue =
*(ckt->CKTrhsOld + here->BALUNbranchpos) *
(*(ckt->CKTrhsOld + here->BALUNposNode)) +
*(ckt->CKTrhsOld + here->BALUNbranchneg) *
(*(ckt->CKTrhsOld + here->BALUNnegNode));
}
return(OK);
default:
return (E_BADPARM);
}
/* NOTREACHED */
}

View File

@ -0,0 +1,94 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
#ifndef BALUN
#define BALUN
#include "ngspice/ifsim.h"
#include "ngspice/cktdefs.h"
#include "ngspice/gendefs.h"
#include "ngspice/complex.h"
/*
* structures to describe Voltage Controlled Voltage Sources
*/
/* information to describe a single instance */
typedef struct sBALUNinstance {
struct GENinstance gen;
#define BALUNmodPtr(inst) ((struct sBALUNmodel *)((inst)->gen.GENmodPtr))
#define BALUNnextInstance(inst) ((struct sBALUNinstance *)((inst)->gen.GENnextInstance))
#define BALUNname gen.GENname
#define BALUNstates gen.GENstate
const int BALUNposNode; /* number of positive node of source */
const int BALUNnegNode; /* number of negative node of source */
const int BALUNcmNode; /* cm node */
const int BALUNdiffNode; /* diff node */
int BALUNbranchpos; /* branch for ipos */
int BALUNbranchneg; /* branch for ineg */
double *BALUNposIbrposPtr;
double *BALUNnegIbrnegPtr;
double *BALUNcmIbrposPtr;
double *BALUNcmIbrnegPtr;
double *BALUNdiffIbrposPtr;
double *BALUNdiffIbrnegPtr;
double *BALUNibrposDiffPtr;
double *BALUNibrposPosPtr;
double *BALUNibrposNegPtr;
double *BALUNibrnegCmPtr;
double *BALUNibrnegPosPtr;
double *BALUNibrnegNegPtr;
int BALUNsenParmNo; /* parameter # for sensitivity use;
set equal to 0 if not a design parameter*/
} BALUNinstance ;
/* per model data */
typedef struct sBALUNmodel { /* model structure for a source */
struct GENmodel gen;
#define BALUNmodType gen.GENmodType
#define BALUNnextModel(inst) ((struct sBALUNmodel *)((inst)->gen.GENnextModel))
#define BALUNinstances(inst) ((BALUNinstance *)((inst)->gen.GENinstances))
#define BALUNmodName gen.GENmodName
} BALUNmodel;
/* device parameters */
enum {
BALUN_POS_NODE = 1,
BALUN_NEG_NODE,
BALUN_DIFF_NODE,
BALUN_CM_NODE,
BALUN_BRPOS,
BALUN_BRNEG,
BALUN_POWER,
};
/* model parameters */
/* device questions */
enum {
BALUN_QUEST_NONE = 201,
};
/* model questions */
#include "balunext.h"
#endif /*BALUN*/

View File

@ -0,0 +1,12 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
extern int BALUNask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*);
extern int BALUNload(GENmodel*,CKTcircuit*);
extern int BALUNparam(int,IFvalue*,GENinstance*,IFvalue*);
extern int BALUNpzLoad(GENmodel*,CKTcircuit*,SPcomplex*);
extern int BALUNsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*);
extern int BALUNunsetup(GENmodel*,CKTcircuit*);

View File

@ -0,0 +1,76 @@
#include "ngspice/config.h"
#include "ngspice/devdefs.h"
#include "balunitf.h"
#include "balunext.h"
#include "baluninit.h"
SPICEdev BALUNinfo = {
.DEVpublic = {
.name = "BALUN",
.description = "Ideal balun",
.terms = &BALUNnSize,
.numNames = &BALUNnSize,
.termNames = BALUNnames,
.numInstanceParms = &BALUNpTSize,
.instanceParms = BALUNpTable,
.numModelParms = NULL,
.modelParms = NULL,
.flags = DEV_DEFAULT,
#ifdef XSPICE
.cm_func = NULL,
.num_conn = 0,
.conn = NULL,
.num_param = 0,
.param = NULL,
.num_inst_var = 0,
.inst_var = NULL,
#endif
},
.DEVparam = BALUNparam,
.DEVmodParam = NULL,
.DEVload = BALUNload,
.DEVsetup = BALUNsetup,
.DEVunsetup = BALUNunsetup,
.DEVpzSetup = BALUNsetup,
.DEVtemperature = NULL,
.DEVtrunc = NULL,
.DEVfindBranch = NULL,
.DEVacLoad = BALUNload,
.DEVaccept = NULL,
.DEVdestroy = NULL,
.DEVmodDelete = NULL,
.DEVdelete = NULL,
.DEVsetic = NULL,
.DEVask = BALUNask,
.DEVmodAsk = NULL,
.DEVpzLoad = BALUNpzLoad,
.DEVconvTest = NULL,
.DEVsenSetup = NULL,
.DEVsenLoad = NULL,
.DEVsenUpdate = NULL,
.DEVsenAcLoad = NULL,
.DEVsenPrint = NULL,
.DEVsenTrunc = NULL,
.DEVdisto = NULL,
.DEVnoise = NULL,
.DEVsoaCheck = NULL,
.DEVinstSize = &BALUNiSize,
.DEVmodSize = &BALUNmSize,
#ifdef CIDER
.DEVdump = NULL,
.DEVacct = NULL,
#endif
};
SPICEdev *
get_balun_info(void)
{
return &BALUNinfo;
}

View File

@ -0,0 +1,11 @@
#ifndef _VCVSINIT_H
#define _VCVSINIT_H
extern IFparm BALUNpTable[ ];
extern char *BALUNnames[ ];
extern int BALUNpTSize;
extern int BALUNnSize;
extern int BALUNiSize;
extern int BALUNmSize;
#endif

View File

@ -0,0 +1,9 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
**********/
#ifndef DEV_BALUN
#define DEV_BALUN
SPICEdev *get_balun_info(void);
#endif

View File

@ -0,0 +1,57 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/*
*/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "balundefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/*ARGSUSED*/
int
BALUNload(GENmodel *inModel, CKTcircuit *ckt)
/* actually load the current voltage value into the
* sparse matrix previously provided
*/
{
BALUNmodel *model = (BALUNmodel *)inModel;
BALUNinstance *here;
NG_IGNORE(ckt);
/* loop through all the voltage source models */
for( ; model != NULL; model = BALUNnextModel(model)) {
/* loop through all the instances of the model */
for (here = BALUNinstances(model); here != NULL ;
here=BALUNnextInstance(here)) {
/* currents to and from nodes */
*(here->BALUNposIbrposPtr) -= 1.0;
*(here->BALUNnegIbrnegPtr) -= 1.0;
/* icm = ipos + ineg */
*(here->BALUNcmIbrposPtr) += 1.0;
*(here->BALUNcmIbrnegPtr) += 1.0;
/* idiff = (ipos - ineg)/2 */
*(here->BALUNdiffIbrposPtr) += 0.5;
*(here->BALUNdiffIbrnegPtr) -= 0.5;
/* vd = vp - vn */
*(here->BALUNibrposDiffPtr) += 1.0 ;
*(here->BALUNibrposPosPtr) -= 1.0 ;
*(here->BALUNibrposNegPtr) += 1.0 ;
/* vc = (vp + vn)/2 */
*(here->BALUNibrnegCmPtr) += 1.0 ;
*(here->BALUNibrnegPosPtr) -= 0.5 ;
*(here->BALUNibrnegNegPtr) -= 0.5 ;
}
}
return(OK);
}

View File

@ -0,0 +1,28 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/*
*/
#include "ngspice/ngspice.h"
#include "ngspice/ifsim.h"
#include "balundefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/* ARGSUSED */
int
BALUNparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
{
BALUNinstance *here = (BALUNinstance *)inst;
NG_IGNORE(select);
switch(param) {
default:
return(E_BADPARM);
}
return(OK);
}

View File

@ -0,0 +1,58 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/*
*/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "ngspice/complex.h"
#include "ngspice/sperror.h"
#include "balundefs.h"
#include "ngspice/suffix.h"
/*ARGSUSED*/
int
BALUNpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
/* actually load the current voltage value into the
* sparse matrix previously provided
*/
{
BALUNmodel *model = (BALUNmodel *)inModel;
BALUNinstance *here;
NG_IGNORE(s);
NG_IGNORE(ckt);
/* loop through all the voltage source models */
for( ; model != NULL; model = BALUNnextModel(model)) {
/* loop through all the instances of the model */
for (here = BALUNinstances(model); here != NULL ;
here=BALUNnextInstance(here)) {
/* currents to and from nodes */
*(here->BALUNposIbrposPtr) -= 1.0;
*(here->BALUNnegIbrnegPtr) -= 1.0;
/* icm = ipos + ineg */
*(here->BALUNcmIbrposPtr) += 1.0;
*(here->BALUNcmIbrnegPtr) += 1.0;
/* idiff = (ipos - ineg)/2 */
*(here->BALUNdiffIbrposPtr) += 0.5;
*(here->BALUNdiffIbrnegPtr) -= 0.5;
/* vd = vp - vn */
*(here->BALUNibrposDiffPtr) += 1.0 ;
*(here->BALUNibrposPosPtr) -= 1.0 ;
*(here->BALUNibrposNegPtr) += 1.0 ;
/* vc = (vp + vn)/2 */
*(here->BALUNibrnegCmPtr) += 1.0 ;
*(here->BALUNibrnegPosPtr) -= 0.5 ;
*(here->BALUNibrnegNegPtr) -= 0.5 ;
}
}
return(OK);
}

View File

@ -0,0 +1,100 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
#include "ngspice/ngspice.h"
#include "ngspice/smpdefs.h"
#include "ngspice/cktdefs.h"
#include "balundefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/*ARGSUSED*/
int
BALUNsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
{
BALUNmodel *model = (BALUNmodel *)inModel;
BALUNinstance *here;
int error;
CKTnode *tmp;
NG_IGNORE(states);
/* loop through all the voltage source models */
for( ; model != NULL; model = BALUNnextModel(model)) {
/* loop through all the instances of the model */
for (here = BALUNinstances(model); here != NULL ;
here=BALUNnextInstance(here)) {
if(here->BALUNposNode == here->BALUNnegNode) {
SPfrontEnd->IFerrorf (ERR_FATAL,
"instance %s is a shorted BALUN", here->BALUNname);
return(E_UNSUPP);
}
if(here->BALUNcmNode == here->BALUNdiffNode) {
SPfrontEnd->IFerrorf (ERR_FATAL,
"instance %s is a shorted BALUN", here->BALUNname);
return(E_UNSUPP);
}
if(here->BALUNbranchpos == 0) {
error = CKTmkCur(ckt,&tmp,here->BALUNname,"branchpos");
if(error) return(error);
here->BALUNbranchpos = tmp->number;
}
if(here->BALUNbranchneg == 0) {
error = CKTmkCur(ckt,&tmp,here->BALUNname,"branchneg");
if(error) return(error);
here->BALUNbranchneg = tmp->number;
}
/* macro to make elements with built in test for out of memory */
#define TSTALLOC(ptr,first,second) \
do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
return(E_NOMEM);\
} } while(0)
TSTALLOC(BALUNposIbrposPtr, BALUNposNode, BALUNbranchpos);
TSTALLOC(BALUNnegIbrnegPtr, BALUNnegNode, BALUNbranchneg);
TSTALLOC(BALUNcmIbrposPtr, BALUNcmNode, BALUNbranchpos);
TSTALLOC(BALUNcmIbrnegPtr, BALUNcmNode, BALUNbranchneg);
TSTALLOC(BALUNdiffIbrposPtr, BALUNdiffNode, BALUNbranchpos);
TSTALLOC(BALUNdiffIbrnegPtr, BALUNdiffNode, BALUNbranchneg);
TSTALLOC(BALUNibrposDiffPtr, BALUNbranchpos, BALUNdiffNode);
TSTALLOC(BALUNibrposPosPtr, BALUNbranchpos, BALUNposNode);
TSTALLOC(BALUNibrposNegPtr, BALUNbranchpos, BALUNnegNode);
TSTALLOC(BALUNibrnegCmPtr, BALUNbranchneg, BALUNcmNode);
TSTALLOC(BALUNibrnegPosPtr, BALUNbranchneg, BALUNposNode);
TSTALLOC(BALUNibrnegNegPtr, BALUNbranchneg, BALUNnegNode);
}
}
return(OK);
}
int
BALUNunsetup(GENmodel *inModel, CKTcircuit *ckt)
{
BALUNmodel *model;
BALUNinstance *here;
for (model = (BALUNmodel *)inModel; model != NULL;
model = BALUNnextModel(model))
{
for (here = BALUNinstances(model); here != NULL;
here=BALUNnextInstance(here))
{
if (here->BALUNbranchpos > 0)
CKTdltNNum(ckt, here->BALUNbranchpos);
here->BALUNbranchpos = 0;
if (here->BALUNbranchneg > 0)
CKTdltNNum(ckt, here->BALUNbranchneg);
here->BALUNbranchneg = 0;
}
}
return OK;
}

View File

@ -142,6 +142,9 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */
#ifdef NDEV
#include "ndev/ndevitf.h"
#endif
#ifdef WITH_LOOPANA
#include "balun/balunitf.h"
#endif
static SPICEdev *(*static_devices[])(void) = {
/* URC device MUST precede both resistors and capacitors */
@ -217,6 +220,10 @@ static SPICEdev *(*static_devices[])(void) = {
get_ndev_info,
#endif
#ifdef WITH_LOOPANA
get_balun_info,
#endif
};
static int DEVNUM = NUMELEMS(static_devices);

View File

@ -69,6 +69,10 @@ libinp_la_SOURCES = \
sperror.c \
inpxx.h
if LOOPANA_WANTED
libinp_la_SOURCES += inp2gen.c
endif
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/frontend
AM_CFLAGS = $(STATIC)
AM_YFLAGS = -d

View File

@ -0,0 +1,155 @@
/*******************************************************************************
* Copyright 2020 Florian Ballenegger, Anamosic Ballenegger Design
*******************************************************************************
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "ngspice/ngspice.h"
#include <stdio.h>
#include "ngspice/ifsim.h"
#include "ngspice/inpdefs.h"
#include "ngspice/inpmacs.h"
#include "ngspice/fteext.h"
#include "inpxx.h"
#include "ngspice/cktdefs.h"
int INP2gentype(char* line)
{
int i;
char c;
for(i=0;c=line[i];i++)
if(!isblank(c))
break;
if(line[i]=='.') return 0;
if(line[i]=='*') return 0;
if(line[i]=='$') return 0;
for(;c=line[i];i++)
{
if(isblank(c))
return 0;
if(c=='#')
return i+1;
}
return 0;
}
int INP2GEN(CKTcircuit *ckt, INPtables * tab, struct card *current)
{
/* <inst>#<devtype> node1 node2 ... noden param=val */
int type; /* the type the model says it is */
int idx, len;
char *line; /* the part of the current line left to parse */
char *name; /* a name */
CKTnode *node; /* a node pointer */
int error; /* error code temporary */
GENinstance *fast; /* pointer to the actual instance */
IFvalue ptemp; /* a value structure to package resistance into */
IFuid uid; /* uid of default model to be created */
GENmodel* genmod;
line = current->line;
idx=INP2gentype(line);
if(!idx)
return 0; /* not a new generic instance format */
/* calc length of device type string */
for(len=0;line[idx+len];len++)
if(isblank(line[idx+len]))
break;
if(len==0) return 0;
/* look if find this device */
for (type = 0; type < ft_sim->numDevices; type++) {
if(ft_sim->devices[type])
if(strlen(ft_sim->devices[type]->name)==len)
if(strncasecmp(&line[idx], ft_sim->devices[type]->name, len)==0)
break;
}
if(type==ft_sim->numDevices) { /* not found */
LITERR("Device type not supported by this binary\n");
return 0;
}
if (1) {
/* create default model */
name = dup_string(ft_sim->devices[type]->name,len);
IFnewUid(ckt, &uid, NULL, name, UID_MODEL, NULL);
genmod = ft_sim->findModel(ckt, uid);
if(!genmod)
IFC(newModel, (ckt, type, &genmod, uid));
}
name = dup_string(line, idx-1);
IFC(newInstance, (ckt, genmod, &fast, name));
if(0) printf("Instance name: %s\n", name);
line = &line[idx+len];
/* parse node connections and bind nodes */
for(idx=0;idx<*(ft_sim->devices[type]->terms);idx++)
{
INPgetNetTok(&line, &name, 1);
INPtermInsert(ckt, &name, tab, &node);
IFC(bindNode, (ckt, fast, idx+1, node));
if(0) printf("bind term %d to %s\n", idx, node->name);
}
/* parse parameters and assign parameters */
while(*line)
{
INPgetTok(&line, &name, 0);
if(*line!='=') {
printf("Expect param=val format for %s, got %c\n", name, *line);
LITERR("Expect param=val format\n");
return(0);
}
line++; /* skip '=' */
for(idx=0;idx<*(ft_sim->devices[type]->numInstanceParms);idx++)
if(strcmp(name, ft_sim->devices[type]->instanceParms[idx].keyword)==0)
break;
tfree(name); /* don't need it anymore, we still know the keyword */
if(idx<*(ft_sim->devices[type]->numInstanceParms))
{ /* found */
int dataType;
IFvalue *parm;
dataType = ft_sim->devices[type]->instanceParms[idx].dataType;
parm = INPgetValue(ckt, &line, dataType, tab);
GCA(INPpName, (ft_sim->devices[type]->instanceParms[idx].keyword, parm, ckt, type, fast));
if(0) printf("Assign %s\n", ft_sim->devices[type]->instanceParms[idx].keyword);
}
else
{
LITERR("Unrecognized parameter\n");
return(0);
}
}
}

View File

@ -16,6 +16,22 @@ Author: 1985 Thomas L. Quarles
/* gtri - end - wbk - 11/9/90 */
#endif
#ifdef WITH_LOOPANA
/* detect A<instname>#<devtype> */
int INPlookahead(char* line)
{
int i;
char c;
for(i=1;c=line[i];i++)
{
if(isblank(c))
return 0;
if(c=='#')
return i+1;
}
return 0;
}
#endif
/* uncomment to trace in this file */
/*#define TRACE*/
@ -90,7 +106,11 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
c = *(current->line);
if(islower_c(c))
c = toupper_c(c);
#ifdef WITH_LOOPANA
if(INP2GEN(ckt, tab, current))
; /* well done */
else
#endif
switch (c) {
case ' ':
@ -98,11 +118,8 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
case '\t':
/* blank line (tab leading) */
break;
#ifdef XSPICE
/* gtri - add - wbk - 10/23/90 - add case for 'A' devices */
case 'A': /* Aname <cm connections> <mname> */
case 'A':
MIF_INP2A(ckt, tab, current);
ckt->CKTadevFlag = 1; /* an 'A' device is requested */
break;

View File

@ -33,6 +33,9 @@ void INP2W(CKTcircuit *ckt, INPtables *tab, struct card *current);
void INP2Y(CKTcircuit *ckt, INPtables *tab, struct card *current);
void INP2Z(CKTcircuit *ckt, INPtables *tab, struct card *current);
#ifdef WITH_LOOPANA
int INP2GEN(CKTcircuit *ckt, INPtables * tab, struct card *current);
#endif
/* ptfuncs.c */