add nullator and norator devices

This commit is contained in:
Florian Ballenegger 2020-10-05 18:23:38 +02:00
parent 9fff864606
commit b8718498e0
34 changed files with 1435 additions and 5 deletions

View File

@ -1262,6 +1262,8 @@ AC_CONFIG_FILES([Makefile
src/spicelib/devices/numd2/Makefile
src/spicelib/devices/numos/Makefile
src/spicelib/devices/balun/Makefile
src/spicelib/devices/nullator/Makefile
src/spicelib/devices/norator/Makefile
src/spicelib/parser/Makefile
src/ciderlib/Makefile
src/ciderlib/input/Makefile

View File

@ -135,7 +135,9 @@ ngspice_LDADD += spicelib/devices/ndev/libndev.la
endif
if LOOPANA_WANTED
ngspice_LDADD += spicelib/devices/balun/libbalun.la
ngspice_LDADD += spicelib/devices/balun/libbalun.la \
spicelib/devices/nullator/libnula.la \
spicelib/devices/norator/libnora.la
endif
if NUMDEV_WANTED
@ -418,7 +420,9 @@ libspice_la_LIBADD += \
endif
if LOOPANA_WANTED
libspice_la_LIBADD += spicelib/devices/balun/libbalun.la
libspice_la_LIBADD += spicelib/devices/balun/libbalun.la \
spicelib/devices/nullator/libnula.la \
spicelib/devices/norator/libnora.la
endif
if NUMDEV_WANTED
@ -537,7 +541,9 @@ libngspice_la_LIBADD += \
endif
if LOOPANA_WANTED
libngspice_la_LIBADD += spicelib/devices/balun/libbalun.la
libngspice_la_LIBADD += spicelib/devices/balun/libbalun.la \
spicelib/devices/nullator/libnula.la \
spicelib/devices/norator/libnora.la
endif
if NUMDEV_WANTED

View File

@ -62,7 +62,7 @@ SUBDIRS += nbjt nbjt2 numd numd2 numos
endif
if LOOPANA_WANTED
SUBDIRS += balun
SUBDIRS += balun nullator norator
endif
@ -123,7 +123,9 @@ DIST_SUBDIRS = \
numd \
numd2 \
numos \
balun
balun \
nullator \
norator
noinst_LTLIBRARIES = libdev.la

View File

@ -144,6 +144,8 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */
#endif
#ifdef WITH_LOOPANA
#include "balun/balunitf.h"
#include "nullator/nulaitf.h"
#include "norator/noraitf.h"
#endif
static SPICEdev *(*static_devices[])(void) = {
@ -222,6 +224,8 @@ static SPICEdev *(*static_devices[])(void) = {
#ifdef WITH_LOOPANA
get_balun_info,
get_nula_info,
get_nora_info,
#endif
};

View File

@ -0,0 +1,28 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = libnora.la
libnora_la_SOURCES = \
nora.c \
noraask.c \
noradefs.h \
noraext.h \
norafbr.c \
norainit.c \
norainit.h \
noraitf.h \
noraload.c \
norapar.c \
norapzld.c \
noraset.c
# norasacl.c \
# norasld.c \
# norasprt.c \
# norasset.c
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
AM_CFLAGS = $(STATIC)
MAINTAINERCLEANFILES = Makefile.in

View File

@ -0,0 +1,34 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "noradefs.h"
#include "ngspice/suffix.h"
IFparm NORApTable[] = { /* parameters */
OPU("pos_node", NORA_POS_NODE, IF_INTEGER, "Positive node of source"),
OPU("neg_node", NORA_NEG_NODE, IF_INTEGER, "Negative node of source"),
IP("ic", NORA_IC, IF_REAL, "Initial condition of branch current"),
OP("i", NORA_CURRENT, IF_REAL, "Output current"),
OP("v", NORA_VOLTS, IF_REAL, "Output voltage"),
OP("p", NORA_POWER, IF_REAL, "Power"),
};
char *NORAnames[] = {
"V+",
"V-",
};
int NORAnSize = NUMELEMS(NORAnames);
int NORApTSize = NUMELEMS(NORApTable);
int NORAmPTSize = 0;
int NORAiSize = sizeof(NORAinstance);
int NORAmSize = sizeof(NORAmodel);

View File

@ -0,0 +1,77 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "noradefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/* ARGSUSED */
int
NORAask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *select)
{
NORAinstance *here = (NORAinstance *)inst;
double vr;
double vi;
double sr;
double si;
double vm;
static char *msg = "Current and power not available for ac analysis";
switch(which) {
case NORA_POS_NODE:
value->iValue = here->NORAposNode;
return (OK);
case NORA_NEG_NODE:
value->iValue = here->NORAnegNode;
return (OK);
case NORA_IC:
value->rValue = here->NORAinitCond;
return (OK);
case NORA_BR:
value->iValue = here->NORAbranch;
return (OK);
case NORA_CURRENT :
if (ckt->CKTcurrentAnalysis & DOING_AC) {
errMsg = TMALLOC(char, strlen(msg) + 1);
errRtn = "NORAask";
strcpy(errMsg,msg);
return(E_ASKCURRENT);
} else {
value->rValue = *(ckt->CKTrhsOld + here->NORAbranch);
}
return(OK);
case NORA_VOLTS :
value->rValue = (*(ckt->CKTrhsOld + here->NORAposNode) -
*(ckt->CKTrhsOld + here->NORAnegNode));
return(OK);
case NORA_POWER :
if (ckt->CKTcurrentAnalysis & DOING_AC) {
errMsg = TMALLOC(char, strlen(msg) + 1);
errRtn = "NORAask";
strcpy(errMsg,msg);
return(E_ASKPOWER);
} else {
value->rValue = *(ckt->CKTrhsOld + here->NORAbranch) *
(*(ckt->CKTrhsOld + here->NORAposNode) -
*(ckt->CKTrhsOld + here->NORAnegNode));
}
return(OK);
default:
return (E_BADPARM);
}
/* NOTREACHED */
}

View File

@ -0,0 +1,81 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
#ifndef NORA
#define NORA
#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 sNORAinstance {
struct GENinstance gen;
#define NORAmodPtr(inst) ((struct sNORAmodel *)((inst)->gen.GENmodPtr))
#define NORAnextInstance(inst) ((struct sNORAinstance *)((inst)->gen.GENnextInstance))
#define NORAname gen.GENname
#define NORAstates gen.GENstate
const int NORAposNode; /* number of positive node of source */
const int NORAnegNode; /* number of negative node of source */
int NORAbranch; /* equation number of branch equation added for v source */
double NORAinitCond; /* initial condition (of branch current) */
double *NORAposIbrPtr; /* pointer to sparse matrix element at
* (positive node, branch equation) */
double *NORAnegIbrPtr; /* pointer to sparse matrix element at
* (negative node, branch equation) */
} NORAinstance ;
#define NORAvOld NORAstates
#define NORAcontVOld NORAstates + 1
/* per model data */
typedef struct sNORAmodel { /* model structure for a source */
struct GENmodel gen;
#define NORAmodType gen.GENmodType
#define NORAnextModel(inst) ((struct sNORAmodel *)((inst)->gen.GENnextModel))
#define NORAinstances(inst) ((NORAinstance *)((inst)->gen.GENinstances))
#define NORAmodName gen.GENmodName
} NORAmodel;
/* device parameters */
enum {
NORA_POS_NODE = 1,
NORA_NEG_NODE,
NORA_BR,
NORA_IC,
NORA_CURRENT,
NORA_POWER,
NORA_VOLTS,
};
/* model parameters */
/* model questions */
#include "noraext.h"
#endif /*NORA*/

View File

@ -0,0 +1,23 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
extern int NORAask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*);
extern int NORAfindBr(CKTcircuit*,GENmodel*,IFuid);
extern int NORAload(GENmodel*,CKTcircuit*);
extern int NORAparam(int,IFvalue*,GENinstance*,IFvalue*);
extern int NORAsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*);
extern int NORAunsetup(GENmodel*,CKTcircuit*);
extern int NORApzLoad(GENmodel*,CKTcircuit*,SPcomplex*);
/*
extern int NORAsAcLoad(GENmodel*,CKTcircuit*);
extern int NORAsLoad(GENmodel*,CKTcircuit*);
extern int NORAsSetup(SENstruct*,GENmodel*);
extern void NORAsPrint(GENmodel*,CKTcircuit*);
*/

View File

@ -0,0 +1,42 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "noradefs.h"
#include "ngspice/trandefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
int
NORAfindBr(CKTcircuit *ckt, GENmodel *inModel, IFuid name)
{
NORAmodel *model = (NORAmodel *)inModel;
NORAinstance *here;
int error;
CKTnode *tmp;
for( ; model != NULL; model = NORAnextModel(model)) {
for (here = NORAinstances(model); here != NULL;
here = NORAnextInstance(here)) {
if(here->NORAname == name) {
if(here->NORAbranch == 0) {
error = CKTmkCur(ckt,&tmp,here->NORAname,"branch");
if(error) return(error);
here->NORAbranch = tmp->number;
}
return(here->NORAbranch);
}
}
}
return(0);
}

View File

@ -0,0 +1,80 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
#include "ngspice/config.h"
#include "ngspice/devdefs.h"
#include "noraitf.h"
#include "noraext.h"
#include "norainit.h"
SPICEdev NORAinfo = {
.DEVpublic = {
.name = "Norator",
.description = "Norator - arbitrary current source",
.terms = &NORAnSize,
.numNames = &NORAnSize,
.termNames = NORAnames,
.numInstanceParms = &NORApTSize,
.instanceParms = NORApTable,
.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 = NORAparam,
.DEVmodParam = NULL,
.DEVload = NORAload,
.DEVsetup = NORAsetup,
.DEVunsetup = NORAunsetup,
.DEVpzSetup = NORAsetup,
.DEVtemperature = NULL,
.DEVtrunc = NULL,
.DEVfindBranch = NORAfindBr,
.DEVacLoad = NORAload,
.DEVaccept = NULL,
.DEVdestroy = NULL,
.DEVmodDelete = NULL,
.DEVdelete = NULL,
.DEVsetic = NULL,
.DEVask = NORAask,
.DEVmodAsk = NULL,
.DEVpzLoad = NORApzLoad,
.DEVconvTest = NULL,
.DEVsenSetup = NULL,
.DEVsenLoad = NULL,
.DEVsenUpdate = NULL,
.DEVsenAcLoad = NULL,
.DEVsenPrint = NULL,
.DEVsenTrunc = NULL,
.DEVdisto = NULL,
.DEVnoise = NULL,
.DEVsoaCheck = NULL,
.DEVinstSize = &NORAiSize,
.DEVmodSize = &NORAmSize,
#ifdef CIDER
.DEVdump = NULL,
.DEVacct = NULL,
#endif
};
SPICEdev *
get_nora_info(void)
{
return &NORAinfo;
}

View File

@ -0,0 +1,15 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
#ifndef _NORAINIT_H
#define _NORAINIT_H
extern IFparm NORApTable[ ];
extern char *NORAnames[ ];
extern int NORApTSize;
extern int NORAnSize;
extern int NORAiSize;
extern int NORAmSize;
#endif

View File

@ -0,0 +1,13 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
**********/
#ifndef DEV_NORA
#define DEV_NORA
SPICEdev *get_nora_info(void);
#endif

View File

@ -0,0 +1,48 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "noradefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/*ARGSUSED*/
int
NORAload(GENmodel *inModel, CKTcircuit *ckt)
/* actually load the current voltage value into the
* sparse matrix previously provided
*/
{
NORAmodel *model = (NORAmodel *)inModel;
NORAinstance *here;
NG_IGNORE(ckt);
/* loop through all the voltage source models */
for( ; model != NULL; model = NORAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NORAinstances(model); here != NULL ;
here=NORAnextInstance(here)) {
*(here->NORAposIbrPtr) += 1.0 ;
*(here->NORAnegIbrPtr) -= 1.0 ;
/* equations to be loaded by a nullator :
*(here->NORAibrContPosPtr) += 1.0 ;
*(here->NORAibrContNegPtr) -= 1.0 ;
*(ckt->CKTrhs + (here->NORAbranch)) += here->NORAoffset;
*/
}
}
return(OK);
}

View File

@ -0,0 +1,32 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "noradefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/* ARGSUSED */
int
NORAparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
{
NORAinstance *here = (NORAinstance *)inst;
NG_IGNORE(select);
switch(param) {
default:
return(E_BADPARM);
}
return(OK);
}

View File

@ -0,0 +1,46 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "noradefs.h"
#include "ngspice/suffix.h"
/* file not used - use regular load function */
/*ARGSUSED*/
int
NORApzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
/* actually load the current voltage value into the
* sparse matrix previously provided
*/
{
NORAmodel *model = (NORAmodel *)inModel;
NORAinstance *here;
NG_IGNORE(s);
NG_IGNORE(ckt);
/* loop through all the voltage source models */
for( ; model != NULL; model = NORAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NORAinstances(model); here != NULL ;
here=NORAnextInstance(here)) {
*(here->NORAposIbrPtr) += 1.0 ;
*(here->NORAnegIbrPtr) -= 1.0 ;
}
}
return(OK);
}

View File

@ -0,0 +1,54 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/*
*/
/* actually load the current ac sensitivity information into the
* array previously provided
*/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "noradefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
int
NORAsAcLoad(GENmodel *inModel, CKTcircuit *ckt)
{
NORAmodel *model = (NORAmodel *)inModel;
NORAinstance *here;
double vc;
double ivc;
/* loop through all the voltage source models */
for( ; model != NULL; model = NORAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NORAinstances(model); here != NULL ;
here=NORAnextInstance(here)) {
if(here->NORAsenParmNo){
vc = *(ckt->CKTrhsOld + here->NORAcontPosNode)
- *(ckt->CKTrhsOld + here->NORAcontNegNode);
ivc = *(ckt->CKTirhsOld + here->NORAcontPosNode)
- *(ckt->CKTirhsOld + here->NORAcontNegNode);
*(ckt->CKTsenInfo->SEN_RHS[here->NORAbranch] +
here->NORAsenParmNo) += vc;
*(ckt->CKTsenInfo->SEN_iRHS[here->NORAbranch] +
here->NORAsenParmNo) += ivc;
}
}
}
return(OK);
}

View File

@ -0,0 +1,87 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Created 2020 Florian Ballenegger - based on VCVS code.
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/* load the voltage source structure with those pointers needed later
* for fast matrix loading
*/
#include "ngspice/ngspice.h"
#include "ngspice/smpdefs.h"
#include "ngspice/cktdefs.h"
#include "noradefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/*ARGSUSED*/
int
NORAsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
{
NORAmodel *model = (NORAmodel *)inModel;
NORAinstance *here;
int error;
CKTnode *tmp;
NG_IGNORE(states);
/* loop through all the voltage source models */
for( ; model != NULL; model = NORAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NORAinstances(model); here != NULL ;
here=NORAnextInstance(here)) {
if(here->NORAposNode == here->NORAnegNode) {
SPfrontEnd->IFerrorf (ERR_FATAL,
"instance %s is a shorted NORATOR", here->NORAname);
return(E_UNSUPP);
}
if(here->NORAbranch == 0) {
error = CKTmkCur(ckt,&tmp,here->NORAname,"branch");
if(error) return(error);
here->NORAbranch = 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(NORAposIbrPtr, NORAposNode, NORAbranch);
TSTALLOC(NORAnegIbrPtr, NORAnegNode, NORAbranch);
/*
TSTALLOC(NORAibrContPosPtr, NORAbranch, NORAcontPosNode);
TSTALLOC(NORAibrContNegPtr, NORAbranch, NORAcontNegNode);
*/
}
}
return(OK);
}
int
NORAunsetup(GENmodel *inModel, CKTcircuit *ckt)
{
NORAmodel *model;
NORAinstance *here;
for (model = (NORAmodel *)inModel; model != NULL;
model = NORAnextModel(model))
{
for (here = NORAinstances(model); here != NULL;
here=NORAnextInstance(here))
{
if (here->NORAbranch > 0)
CKTdltNNum(ckt, here->NORAbranch);
here->NORAbranch = 0;
}
}
return OK;
}

View File

@ -0,0 +1,30 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = libnula.la
libnula_la_SOURCES = \
nula.c \
nulaask.c \
nuladefs.h \
nulaext.h \
nulainit.c \
nulainit.h \
nulaitf.h \
nulaload.c \
nulapar.c \
nulaset.c \
nulapzld.c
# nulafbr.c
# nulapzld.c \
# nulasacl.c \
# nulaset.c \
# nulasld.c \
# nulasprt.c \
# nulasset.c
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
AM_CFLAGS = $(STATIC)
MAINTAINERCLEANFILES = Makefile.in

View File

@ -0,0 +1,33 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "nuladefs.h"
#include "ngspice/suffix.h"
IFparm NULApTable[] = { /* parameters */
IOP("offset", NULA_OFFSET, IF_REAL,"Control offset"),
OPU("cont_p_node",NULA_CONT_P_NODE,IF_INTEGER,
"Positive node of nullator"),
OPU("cont_n_node",NULA_CONT_N_NODE,IF_INTEGER,
"Negative node of nullator"),
};
char *NULAnames[] = {
"VC+",
"VC-"
};
int NULAnSize = NUMELEMS(NULAnames);
int NULApTSize = NUMELEMS(NULApTable);
int NULAmPTSize = 0;
int NULAiSize = sizeof(NULAinstance);
int NULAmSize = sizeof(NULAmodel);

View File

@ -0,0 +1,39 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "nuladefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/* ARGSUSED */
int
NULAask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *select)
{
NULAinstance *here = (NULAinstance *)inst;
switch(which) {
case NULA_CONT_P_NODE:
value->iValue = here->NULAcontPosNode;
return (OK);
case NULA_CONT_N_NODE:
value->iValue = here->NULAcontNegNode;
return (OK);
default:
return (E_BADPARM);
}
/* NOTREACHED */
}

View File

@ -0,0 +1,79 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
#ifndef NULA
#define NULA
#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 sNULAinstance {
struct GENinstance gen;
#define NULAmodPtr(inst) ((struct sNULAmodel *)((inst)->gen.GENmodPtr))
#define NULAnextInstance(inst) ((struct sNULAinstance *)((inst)->gen.GENnextInstance))
#define NULAname gen.GENname
#define NULAstates gen.GENstate
const int NULAcontPosNode; /* number of positive node of controlling source */
const int NULAcontNegNode; /* number of negative node of controlling source */
int NULAbranch; /* equation number of branch equation added for v source */
double NULAoffset; /* control offset */
double *NULAibrContPosPtr; /* pointer to sparse matrix element at
*(branch equation, control positive node)*/
double *NULAibrContNegPtr; /* pointer to sparse matrix element at
*(branch equation, control negative node)*/
unsigned NULAoffsetGiven :1 ;/* flag to indicate offset given */
} NULAinstance ;
#define NULAvOld NULAstates
#define NULAcontVOld NULAstates + 1
/* per model data */
typedef struct sNULAmodel { /* model structure for a source */
struct GENmodel gen;
#define NULAmodType gen.GENmodType
#define NULAnextModel(inst) ((struct sNULAmodel *)((inst)->gen.GENnextModel))
#define NULAinstances(inst) ((NULAinstance *)((inst)->gen.GENinstances))
#define NULAmodName gen.GENmodName
} NULAmodel;
/* device parameters */
enum {
NULA_OFFSET = 1,
NULA_CONT_P_NODE,
NULA_CONT_N_NODE,
};
/* model parameters */
/* device questions */
/* model questions */
#include "nulaext.h"
#endif /*NULA*/

View File

@ -0,0 +1,23 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
extern int NULAask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*);
extern int NULAfindBr(CKTcircuit*,GENmodel*,IFuid);
extern int NULAload(GENmodel*,CKTcircuit*);
extern int NULAparam(int,IFvalue*,GENinstance*,IFvalue*);
extern int NULAsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*);
extern int NULAunsetup(GENmodel*,CKTcircuit*);
extern int NULApzLoad(GENmodel*,CKTcircuit*,SPcomplex*);
/*
extern int NULAsAcLoad(GENmodel*,CKTcircuit*);
extern int NULAsLoad(GENmodel*,CKTcircuit*);
extern int NULAsSetup(SENstruct*,GENmodel*);
extern void NULAsPrint(GENmodel*,CKTcircuit*);
*/

View File

@ -0,0 +1,80 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
#include "ngspice/config.h"
#include "ngspice/devdefs.h"
#include "nulaitf.h"
#include "nulaext.h"
#include "nulainit.h"
SPICEdev NULAinfo = {
.DEVpublic = {
.name = "Nullator",
.description = "Nullator",
.terms = &NULAnSize,
.numNames = &NULAnSize,
.termNames = NULAnames,
.numInstanceParms = &NULApTSize,
.instanceParms = NULApTable,
.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 = NULAparam,
.DEVmodParam = NULL,
.DEVload = NULAload,
.DEVsetup = NULAsetup,
.DEVunsetup = NULAunsetup,
.DEVpzSetup = NULAsetup,
.DEVtemperature = NULL,
.DEVtrunc = NULL,
.DEVfindBranch = NULL,
.DEVacLoad = NULAload,
.DEVaccept = NULL,
.DEVdestroy = NULL,
.DEVmodDelete = NULL,
.DEVdelete = NULL,
.DEVsetic = NULL,
.DEVask = NULAask,
.DEVmodAsk = NULL,
.DEVpzLoad = NULApzLoad,
.DEVconvTest = NULL,
.DEVsenSetup = NULL,
.DEVsenLoad = NULL,
.DEVsenUpdate = NULL,
.DEVsenAcLoad = NULL,
.DEVsenPrint = NULL,
.DEVsenTrunc = NULL,
.DEVdisto = NULL,
.DEVnoise = NULL,
.DEVsoaCheck = NULL,
.DEVinstSize = &NULAiSize,
.DEVmodSize = &NULAmSize,
#ifdef CIDER
.DEVdump = NULL,
.DEVacct = NULL,
#endif
};
SPICEdev *
get_nula_info(void)
{
return &NULAinfo;
}

View File

@ -0,0 +1,15 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
#ifndef _NULAINIT_H
#define _NULAINIT_H
extern IFparm NULApTable[ ];
extern char *NULAnames[ ];
extern int NULApTSize;
extern int NULAnSize;
extern int NULAiSize;
extern int NULAmSize;
#endif

View File

@ -0,0 +1,13 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
**********/
#ifndef DEV_NULA
#define DEV_NULA
SPICEdev *get_nula_info(void);
#endif

View File

@ -0,0 +1,44 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "nuladefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/*ARGSUSED*/
int
NULAload(GENmodel *inModel, CKTcircuit *ckt)
/* actually load the current voltage value into the
* sparse matrix previously provided
*/
{
NULAmodel *model = (NULAmodel *)inModel;
NULAinstance *here;
NG_IGNORE(ckt);
/* loop through all the voltage source models */
for( ; model != NULL; model = NULAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NULAinstances(model); here != NULL ;
here=NULAnextInstance(here)) {
*(here->NULAibrContPosPtr) += 1.0 ;
*(here->NULAibrContNegPtr) -= 1.0 ;
*(ckt->CKTrhs + (here->NULAbranch)) += here->NULAoffset;
}
}
return(OK);
}

View File

@ -0,0 +1,36 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "nuladefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/* ARGSUSED */
int
NULAparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
{
NULAinstance *here = (NULAinstance *)inst;
NG_IGNORE(select);
switch(param) {
case NULA_OFFSET:
here->NULAoffset = value->rValue;
here->NULAoffsetGiven = TRUE;
break;
default:
return(E_BADPARM);
}
return(OK);
}

View File

@ -0,0 +1,45 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
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 "nuladefs.h"
#include "ngspice/suffix.h"
/*ARGSUSED*/
int
NULApzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
/* actually load the current voltage value into the
* sparse matrix previously provided
*/
{
NULAmodel *model = (NULAmodel *)inModel;
NULAinstance *here;
NG_IGNORE(s);
NG_IGNORE(ckt);
/* loop through all the voltage source models */
for( ; model != NULL; model = NULAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NULAinstances(model); here != NULL ;
here=NULAnextInstance(here)) {
*(here->NULAibrContPosPtr) += 1.0 ;
*(here->NULAibrContNegPtr) -= 1.0 ;
}
}
return(OK);
}

View File

@ -0,0 +1,54 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/*
*/
/* actually load the current ac sensitivity information into the
* array previously provided
*/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "nuladefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
int
NULAsAcLoad(GENmodel *inModel, CKTcircuit *ckt)
{
NULAmodel *model = (NULAmodel *)inModel;
NULAinstance *here;
double vc;
double ivc;
/* loop through all the voltage source models */
for( ; model != NULL; model = NULAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NULAinstances(model); here != NULL ;
here=NULAnextInstance(here)) {
if(here->NULAsenParmNo){
vc = *(ckt->CKTrhsOld + here->NULAcontPosNode)
- *(ckt->CKTrhsOld + here->NULAcontNegNode);
ivc = *(ckt->CKTirhsOld + here->NULAcontPosNode)
- *(ckt->CKTirhsOld + here->NULAcontNegNode);
*(ckt->CKTsenInfo->SEN_RHS[here->NULAbranch] +
here->NULAsenParmNo) += vc;
*(ckt->CKTsenInfo->SEN_iRHS[here->NULAbranch] +
here->NULAsenParmNo) += ivc;
}
}
}
return(OK);
}

View File

@ -0,0 +1,121 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/* load the voltage source structure with those pointers needed later
* for fast matrix loading
*/
#include "ngspice/ngspice.h"
#include "ngspice/smpdefs.h"
#include "ngspice/cktdefs.h"
#include "nuladefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
#include "ngspice/devdefs.h"
/*ARGSUSED*/
int
NULAsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
{
NULAmodel *model = (NULAmodel *)inModel;
NULAinstance *here;
GENinstance *nora;
GENmodel *noramod;
int i, error;
CKTnode *tmp;
NG_IGNORE(states);
noramod = NULL;
nora = NULL;
for (i=0;i<DEVmaxnum;i++)
if (DEVices[i])
if (strcmp(DEVices[i]->DEVpublic.name,"Norator")==0) {
noramod = ckt->CKThead[i];
break;
}
if(i==DEVmaxnum)
if(model && NULAinstances(model)) /* emit warning only if circuit actualy has a nullator */
SPfrontEnd->IFerrorf (ERR_WARNING,
"Norator device needed for nullator, missing.");
if(noramod)
nora = noramod->GENinstances;
/* loop through all the nullator models */
for( ; model != NULL; model = NULAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NULAinstances(model); here != NULL ;
here=NULAnextInstance(here)) {
if(here->NULAcontPosNode == here->NULAcontNegNode) {
SPfrontEnd->IFerrorf (ERR_FATAL,
"instance %s is a shorted nullator", here->NULAname);
return(E_UNSUPP);
}
if(!here->NULAoffsetGiven)
here->NULAoffset = 0.0;
if(here->NULAbranch == 0) {
/* assign a branch from a norator device ... */
if(nora) {
here->NULAbranch = DEVices[i]->DEVfindBranch(ckt, noramod, nora->GENname);
} else {
SPfrontEnd->IFerrorf (ERR_FATAL,
"excess nullators in respect to number of norator");
return(E_UNSUPP);
}
/* point to next norator instance */
nora = nora->GENnextInstance;
if(!nora) {
noramod = noramod->GENnextModel;
if(noramod)
nora = noramod->GENinstances;
}
}
/* 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)
if(here->NULAbranch>0) {
TSTALLOC(NULAibrContPosPtr, NULAbranch, NULAcontPosNode);
TSTALLOC(NULAibrContNegPtr, NULAbranch, NULAcontNegNode);
} else {
SPfrontEnd->IFerrorf (ERR_FATAL,
"failed to find a norator branch for nullator %s", here->NULAname);
return(E_UNSUPP);
}
}
}
return(OK);
}
int
NULAunsetup(GENmodel *inModel, CKTcircuit *ckt)
{
NULAmodel *model;
NULAinstance *here;
for (model = (NULAmodel *)inModel; model != NULL;
model = NULAnextModel(model))
{
for (here = NULAinstances(model); here != NULL;
here=NULAnextInstance(here))
{
here->NULAbranch = 0;
}
}
return OK;
}

View File

@ -0,0 +1,48 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/*
*/
/* actually load the current sensitivity information into the
* array previously provided
*/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "nuladefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
int
NULAsLoad(GENmodel *inModel, CKTcircuit *ckt)
{
NULAmodel *model = (NULAmodel *)inModel;
NULAinstance *here;
double vc;
/* loop through all the voltage source models */
for( ; model != NULL; model = NULAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NULAinstances(model); here != NULL ;
here=NULAnextInstance(here)) {
if(here->NULAsenParmNo){
vc = *(ckt->CKTrhsOld + here->NULAcontPosNode)
- *(ckt->CKTrhsOld + here->NULAcontNegNode);
*(ckt->CKTsenInfo->SEN_RHS[here->NULAbranch] +
here->NULAsenParmNo) += vc;
}
}
}
return(OK);
}

View File

@ -0,0 +1,52 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/*
*/
/* Pretty print the sensitivity info for
* all the NULA in the circuit.
*/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "nuladefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
void
NULAsPrint(GENmodel *inModel, CKTcircuit *ckt)
{
NULAmodel *model = (NULAmodel *)inModel;
NULAinstance *here;
printf("VOLTAGE CONTROLLED VOLTAGE SOURCES-----------------\n");
/* loop through all the voltage source models */
for( ; model != NULL; model = NULAnextModel(model)) {
printf("Model name:%s\n",model->NULAmodName);
/* loop through all the instances of the model */
for (here = NULAinstances(model); here != NULL ;
here=NULAnextInstance(here)) {
printf(" Instance name:%s\n",here->NULAname);
printf(" Positive, negative nodes: %s, %s\n",
CKTnodName(ckt,here->NULAposNode),
CKTnodName(ckt,here->NULAnegNode));
printf(" Controlling Positive, negative nodes: %s, %s\n",
CKTnodName(ckt,here->NULAcontPosNode),
CKTnodName(ckt,here->NULAcontNegNode));
printf(" Branch equation number: %s\n",
CKTnodName(ckt,here->NULAbranch));
printf(" Coefficient: %f\n",here->NULAcoeff);
printf(" NULAsenParmNo:%d\n",here->NULAsenParmNo);
}
}
}

View File

@ -0,0 +1,44 @@
/**********
Author: Florian Ballenegger 2020
Adapted from VCVS device code.
**********/
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
/*
*/
/* loop through all the devices and
* allocate parameter #s to design parameters
*/
#include "ngspice/ngspice.h"
#include "ngspice/smpdefs.h"
#include "ngspice/cktdefs.h"
#include "nuladefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
int
NULAsSetup(SENstruct *info, GENmodel *inModel)
{
NULAmodel *model = (NULAmodel *)inModel;
NULAinstance *here;
/* loop through all the voltage source models */
for( ; model != NULL; model = NULAnextModel(model)) {
/* loop through all the instances of the model */
for (here = NULAinstances(model); here != NULL ;
here=NULAnextInstance(here)) {
if(here->NULAsenParmNo){
here->NULAsenParmNo = ++(info->SENparms);
}
}
}
return(OK);
}