diff --git a/src/include/ngspice/dllitf.h b/src/include/ngspice/dllitf.h index 702c46abf..b3a68c65d 100644 --- a/src/include/ngspice/dllitf.h +++ b/src/include/ngspice/dllitf.h @@ -6,6 +6,7 @@ #ifndef ngspice_DLLITF_H #define ngspice_DLLITF_H +#include "ngspice/config.h" #include "ngspice/mifproto.h" #include "ngspice/cmproto.h" @@ -82,6 +83,12 @@ struct coreInfo_t { void * ((*dllitf_tmalloc)(size_t)); void * ((*dllitf_trealloc)(const void *, size_t)); void ((*dllitf_txfree)(const void *)); + +#ifdef KLU + int ((*dllitf_MIFbindCSC) (GENmodel *, CKTcircuit *)) ; + int ((*dllitf_MIFbindCSCComplex) (GENmodel *, CKTcircuit *)) ; + int ((*dllitf_MIFbindCSCComplexToReal) (GENmodel *, CKTcircuit *)) ; +#endif }; #endif diff --git a/src/include/ngspice/klu-binding.h b/src/include/ngspice/klu-binding.h index b3f5fa48d..fa47b770a 100644 --- a/src/include/ngspice/klu-binding.h +++ b/src/include/ngspice/klu-binding.h @@ -1,20 +1,54 @@ #ifndef _KLU_BINDING_H #define _KLU_BINDING_H -#define CREATE_KLU_BINDING_TABLE(ptr, binding, a, b) \ - if ((here->a != 0) && (here->b != 0)) { \ - i = here->ptr ; \ +#define CREATE_KLU_BINDING_TABLE(ptr, binding, a, b) \ + if ((here->a != 0) && (here->b != 0)) { \ + i = here->ptr ; \ matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof(BindElement), BindCompare) ; \ - here->binding = matched ; \ - here->ptr = matched->CSC ; \ + here->binding = matched ; \ + here->ptr = matched->CSC ; \ } -#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(ptr, binding, a, b) \ - if ((here->a != 0) && (here->b != 0)) \ +#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(ptr, binding, a, b) \ + if ((here->a != 0) && (here->b != 0)) \ here->ptr = here->binding->CSC_Complex ; -#define CONVERT_KLU_BINDING_TABLE_TO_REAL(ptr, binding, a, b) \ - if ((here->a != 0) && (here->b != 0)) \ +#define CONVERT_KLU_BINDING_TABLE_TO_REAL(ptr, binding, a, b) \ + if ((here->a != 0) && (here->b != 0)) \ here->ptr = here->binding->CSC ; +#ifdef XSPICE +#define CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(ptr, binding, a, b) \ + if ((smp_data_out->a != 0) && (smp_data_out->b != 0)) { \ + i = smp_data_out->ptr ; \ + matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof(BindElement), BindCompare) ; \ + here->binding = matched ; \ + smp_data_out->ptr = matched->CSC ; \ + } + +#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(ptr, binding, a, b) \ + if ((smp_data_out->a != 0) && (smp_data_out->b != 0)) \ + smp_data_out->ptr = here->binding->CSC_Complex ; + +#define CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(ptr, binding, a, b) \ + if ((smp_data_out->a != 0) && (smp_data_out->b != 0)) \ + smp_data_out->ptr = here->binding->CSC ; + +#define CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(ptr, binding, a, b) \ + if ((smp_data_out->a != 0) && (smp_data_cntl->b != 0)) { \ + i = smp_data_out->input[k].port[l].ptr ; \ + matched = (BindElement *) bsearch (&i, BindStruct, nz, sizeof(BindElement), BindCompare) ; \ + here->binding = matched ; \ + smp_data_out->input[k].port[l].ptr = matched->CSC ; \ + } + +#define CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(ptr, binding, a, b) \ + if ((smp_data_out->a != 0) && (smp_data_cntl->b != 0)) \ + smp_data_out->input[k].port[l].ptr = here->binding->CSC_Complex ; + +#define CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(ptr, binding, a, b) \ + if ((smp_data_out->a != 0) && (smp_data_cntl->b != 0)) \ + smp_data_out->input[k].port[l].ptr = here->binding->CSC ; +#endif + #endif diff --git a/src/include/ngspice/mifdefs.h b/src/include/ngspice/mifdefs.h index da654e054..ebad19f03 100644 --- a/src/include/ngspice/mifdefs.h +++ b/src/include/ngspice/mifdefs.h @@ -43,10 +43,13 @@ NON-STANDARD FEATURES =========================================================================== */ -#include "ngspice/mifcmdat.h" -#include "ngspice/gendefs.h" +#include "ngspice/mifcmdat.h" +#include "ngspice/gendefs.h" #include "ngspice/ifsim.h" +#ifdef KLU +#include "ngspice/smpdefs.h" +#endif /* The per-instance data structure */ @@ -85,6 +88,26 @@ struct MIFinstance { int inst_index; /* Index into inst_table in evt struct in ckt */ Mif_Callback_t callback; /* instance callback function */ +#ifdef KLU + BindElement *pos_branchBinding ; + BindElement *neg_branchBinding ; + BindElement *branch_posBinding ; + BindElement *branch_negBinding ; + BindElement *pos_ibranchBinding ; + BindElement *neg_ibranchBinding ; + BindElement *ibranch_posBinding ; + BindElement *ibranch_negBinding ; + BindElement *branch_poscntlBinding ; + BindElement *branch_negcntlBinding ; + BindElement *pos_ibranchcntlBinding ; + BindElement *neg_ibranchcntlBinding ; + BindElement *pos_poscntlBinding ; + BindElement *pos_negcntlBinding ; + BindElement *neg_poscntlBinding ; + BindElement *neg_negcntlBinding ; + BindElement *branch_ibranchcntlBinding ; +#endif + }; diff --git a/src/include/ngspice/mifproto.h b/src/include/ngspice/mifproto.h index 722e4b633..2daabcb93 100644 --- a/src/include/ngspice/mifproto.h +++ b/src/include/ngspice/mifproto.h @@ -154,6 +154,11 @@ extern Mif_Cntl_Src_Type_t MIFget_cntl_src_type( extern char *MIFcopy(char *); +#ifdef KLU +extern int MIFbindCSC (GENmodel*, CKTcircuit*) ; +extern int MIFbindCSCComplex (GENmodel*, CKTcircuit*) ; +extern int MIFbindCSCComplexToReal (GENmodel*, CKTcircuit*) ; +#endif #ifndef CM_IGNORE #define CM_IGNORE(x) (void) (x) diff --git a/src/xspice/cm/cmexport.c b/src/xspice/cm/cmexport.c index f34b2179a..2240eaf01 100644 --- a/src/xspice/cm/cmexport.c +++ b/src/xspice/cm/cmexport.c @@ -91,4 +91,10 @@ struct coreInfo_t coreInfo = GC_realloc, no_free #endif +#ifdef KLU + , + MIFbindCSC, + MIFbindCSCComplex, + MIFbindCSCComplexToReal +#endif }; diff --git a/src/xspice/cmpp/writ_ifs.c b/src/xspice/cmpp/writ_ifs.c index 941abf4ef..21b46f8af 100644 --- a/src/xspice/cmpp/writ_ifs.c +++ b/src/xspice/cmpp/writ_ifs.c @@ -1040,6 +1040,12 @@ static int write_SPICEdev( " .DEVdump = NULL,\n" " .DEVacct = NULL,\n" "#endif\n" + "\n" + "#ifdef KLU\n" + " .DEVbindCSC = MIFbindCSC,\n" + " .DEVbindCSCComplex = MIFbindCSCComplex,\n" + " .DEVbindCSCComplexToReal = MIFbindCSCComplexToReal,\n" + "#endif\n" "};\n\n" ); diff --git a/src/xspice/icm/dlmain.c b/src/xspice/icm/dlmain.c index 02fffe706..c64668991 100644 --- a/src/xspice/icm/dlmain.c +++ b/src/xspice/icm/dlmain.c @@ -430,6 +430,19 @@ void txfree(const void *ptr) { (coreitf->dllitf_txfree)(ptr); } +#ifdef KLU +int MIFbindCSC (GENmodel *inModel, CKTcircuit *ckt) { + return (coreitf->dllitf_MIFbindCSC) (inModel, ckt) ; +} + +int MIFbindCSCComplex (GENmodel *inModel, CKTcircuit *ckt) { + return (coreitf->dllitf_MIFbindCSCComplex) (inModel, ckt) ; +} + +int MIFbindCSCComplexToReal (GENmodel *inModel, CKTcircuit *ckt) { + return (coreitf->dllitf_MIFbindCSCComplexToReal) (inModel, ckt) ; +} +#endif /* fopen_with_path() diff --git a/src/xspice/mif/Makefile.am b/src/xspice/mif/Makefile.am index 60b1b6fdf..6fccc76a1 100644 --- a/src/xspice/mif/Makefile.am +++ b/src/xspice/mif/Makefile.am @@ -21,6 +21,10 @@ libmifxsp_la_SOURCES = \ mifdestr.c \ mif.c +if KLU_WANTED +libmifxsp_la_SOURCES += mifbindCSC.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/xspice/mif/mifbindCSC.c b/src/xspice/mif/mifbindCSC.c new file mode 100644 index 000000000..8fb2260a8 --- /dev/null +++ b/src/xspice/mif/mifbindCSC.c @@ -0,0 +1,507 @@ +/* +** Author: Francesco Lannutti +** Date: 15 March 2020 +** Purpose: KLU binding table routines for XSPICE +*/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "ngspice/sperror.h" +#include "ngspice/klu-binding.h" + +#include "ngspice/mifproto.h" +#include "ngspice/mifdefs.h" + +#include + +static +int +BindCompare (const void *a, const void *b) +{ + BindElement *A, *B ; + A = (BindElement *)a ; + B = (BindElement *)b ; + + return ((int)(A->Sparse - B->Sparse)) ; +} + +int +MIFbindCSC (GENmodel *inModel, CKTcircuit *ckt) +{ + MIFmodel *model = (MIFmodel *)inModel ; + MIFinstance *here ; + double *i ; + BindElement *matched, *BindStruct ; + int ii, j, k, l, num_conn, num_port, num_port_k ; + Mif_Boolean_t is_input, is_output ; + Mif_Cntl_Src_Type_t cntl_src_type ; + Mif_Port_Type_t in_type, out_type, type ; + Mif_Smp_Ptr_t *smp_data_cntl, *smp_data_out ; + size_t nz ; + + BindStruct = ckt->CKTmatrix->CKTbindStruct ; + nz = (size_t)ckt->CKTmatrix->CKTklunz ; + + /* loop through all the MIF models */ + for ( ; model != NULL ; model = MIFnextModel(model)) + { + /* loop through all the instances of the model */ + for (here = MIFinstances(model); here != NULL ; here = MIFnextInstance(here)) + { + /* Skip these expensive allocations if the instance is not analog */ + if(! here->analog) + continue; + + num_conn = here->num_conn; + + /* loop through all connections on this instance */ + /* and create matrix data needed for outputs and */ + /* V sources associated with I inputs */ + for(ii = 0; ii < num_conn; ii++) { + + /* if the connection is null, skip to next connection */ + if(here->conn[ii]->is_null) + continue; + + /* prepare things for convenient access later */ + is_input = here->conn[ii]->is_input; + is_output = here->conn[ii]->is_output; + num_port = here->conn[ii]->size; + + /* loop through all ports on this connection */ + for(j = 0; j < num_port; j++) { + + /* if port is null, skip to next */ + if(here->conn[ii]->port[j]->is_null) + continue; + + /* determine the type of this port */ + type = here->conn[ii]->port[j]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_out = &(here->conn[ii]->port[j]->smp_data); + + /* if it has a voltage source output, */ + /* create the matrix data needed */ + if( (is_output && (type == MIF_VOLTAGE || type == MIF_DIFF_VOLTAGE)) || + (type == MIF_RESISTANCE || type == MIF_DIFF_RESISTANCE) ) { + + /* then make the matrix pointers */ + CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(pos_branch, pos_branchBinding, pos_node, branch); + CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(neg_branch, neg_branchBinding, neg_node, branch); + CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(branch_pos, branch_posBinding, branch, pos_node); + CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(branch_neg, branch_negBinding, branch, neg_node); + } /* end if current input */ + + /* if it is a current input */ + /* create the matrix data needed for the associated zero-valued V source */ + if(is_input && (type == MIF_CURRENT || type == MIF_DIFF_CURRENT)) { + + /* then make the matrix pointers */ + CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(pos_ibranch, pos_ibranchBinding, pos_node, ibranch); + CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(neg_ibranch, neg_ibranchBinding, neg_node, ibranch); + CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(ibranch_pos, ibranch_posBinding, ibranch, pos_node); + CREATE_KLU_BINDING_TABLE_XSPICE_OUTPUTS(ibranch_neg, ibranch_negBinding, ibranch, neg_node); + } /* end if current input */ + } /* end for number of ports */ + } /* end for number of connections */ + + /* now loop through all connections on the instance and create */ + /* matrix data needed for partial derivatives of outputs */ + for(ii = 0; ii < num_conn; ii++) { + + /* if the connection is null or is not an output */ + /* skip to next connection */ + if((here->conn[ii]->is_null) || (! here->conn[ii]->is_output)) + continue; + + /* loop through all ports on this connection */ + + num_port = here->conn[ii]->size; + for(j = 0; j < num_port; j++) { + + /* if port is null, skip to next */ + if(here->conn[ii]->port[j]->is_null) + continue; + + /* determine the type of this output port */ + out_type = here->conn[ii]->port[j]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_out = &(here->conn[ii]->port[j]->smp_data); + + /* for this port, loop through all connections */ + /* and all ports to touch on each possible input */ + for(k = 0; k < num_conn; k++) { + + /* if the connection is null or is not an input */ + /* skip to next connection */ + if((here->conn[k]->is_null) || (! here->conn[k]->is_input)) + continue; + + num_port_k = here->conn[k]->size; + /* loop through all the ports of this connection */ + for(l = 0; l < num_port_k; l++) { + + /* if port is null, skip to next */ + if(here->conn[k]->port[l]->is_null) + continue; + + /* determine the type of this input port */ + in_type = here->conn[k]->port[l]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_cntl = &(here->conn[k]->port[l]->smp_data); + + /* determine type of controlled source according */ + /* to input and output types */ + cntl_src_type = MIFget_cntl_src_type(in_type, out_type); + + switch(cntl_src_type) { + case MIF_VCVS: + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(e.branch_poscntl, branch_poscntlBinding, branch, pos_node); + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(e.branch_negcntl, branch_negcntlBinding, branch, neg_node); + break; + case MIF_ICIS: + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(f.pos_ibranchcntl, pos_ibranchcntlBinding, pos_node, ibranch); + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(f.neg_ibranchcntl, neg_ibranchcntlBinding, neg_node, ibranch); + break; + case MIF_VCIS: + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(g.pos_poscntl, pos_poscntlBinding, pos_node, pos_node); + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(g.pos_negcntl, pos_negcntlBinding, pos_node, neg_node); + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(g.neg_poscntl, neg_poscntlBinding, neg_node, pos_node); + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(g.neg_negcntl, neg_negcntlBinding, neg_node, neg_node); + break; + case MIF_ICVS: + CREATE_KLU_BINDING_TABLE_XSPICE_INPUTS(h.branch_ibranchcntl, branch_ibranchcntlBinding, branch, ibranch); + break; + case MIF_minus_one: + break; + } /* end switch on controlled source type */ + } /* end for number of input ports */ + } /* end for number of input connections */ + } /* end for number of output ports */ + } /* end for number of output connections */ + } + } + + return (OK) ; +} + +int +MIFbindCSCComplex (GENmodel *inModel, CKTcircuit *ckt) +{ + MIFmodel *model = (MIFmodel *)inModel ; + MIFinstance *here ; + int ii, j, k, l, num_conn, num_port, num_port_k ; + Mif_Boolean_t is_input, is_output ; + Mif_Cntl_Src_Type_t cntl_src_type ; + Mif_Port_Type_t in_type, out_type, type ; + Mif_Smp_Ptr_t *smp_data_cntl, *smp_data_out ; + + NG_IGNORE (ckt) ; + + /* loop through all the MIF models */ + for ( ; model != NULL ; model = MIFnextModel(model)) + { + /* loop through all the instances of the model */ + for (here = MIFinstances(model); here != NULL ; here = MIFnextInstance(here)) + { + /* Skip these expensive allocations if the instance is not analog */ + if(! here->analog) + continue; + + num_conn = here->num_conn; + + /* loop through all connections on this instance */ + /* and create matrix data needed for outputs and */ + /* V sources associated with I inputs */ + for(ii = 0; ii < num_conn; ii++) { + + /* if the connection is null, skip to next connection */ + if(here->conn[ii]->is_null) + continue; + + /* prepare things for convenient access later */ + is_input = here->conn[ii]->is_input; + is_output = here->conn[ii]->is_output; + num_port = here->conn[ii]->size; + + /* loop through all ports on this connection */ + for(j = 0; j < num_port; j++) { + + /* if port is null, skip to next */ + if(here->conn[ii]->port[j]->is_null) + continue; + + /* determine the type of this port */ + type = here->conn[ii]->port[j]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_out = &(here->conn[ii]->port[j]->smp_data); + + /* if it has a voltage source output, */ + /* create the matrix data needed */ + if( (is_output && (type == MIF_VOLTAGE || type == MIF_DIFF_VOLTAGE)) || + (type == MIF_RESISTANCE || type == MIF_DIFF_RESISTANCE) ) { + + /* then make the matrix pointers */ + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(pos_branch, pos_branchBinding, pos_node, branch); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(neg_branch, neg_branchBinding, neg_node, branch); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(branch_pos, branch_posBinding, branch, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(branch_neg, branch_negBinding, branch, neg_node); + } /* end if current input */ + + /* if it is a current input */ + /* create the matrix data needed for the associated zero-valued V source */ + if(is_input && (type == MIF_CURRENT || type == MIF_DIFF_CURRENT)) { + + /* then make the matrix pointers */ + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(pos_ibranch, pos_ibranchBinding, pos_node, ibranch); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(neg_ibranch, neg_ibranchBinding, neg_node, ibranch); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(ibranch_pos, ibranch_posBinding, ibranch, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_OUTPUTS(ibranch_neg, ibranch_negBinding, ibranch, neg_node); + } /* end if current input */ + } /* end for number of ports */ + } /* end for number of connections */ + + /* now loop through all connections on the instance and create */ + /* matrix data needed for partial derivatives of outputs */ + for(ii = 0; ii < num_conn; ii++) { + + /* if the connection is null or is not an output */ + /* skip to next connection */ + if((here->conn[ii]->is_null) || (! here->conn[ii]->is_output)) + continue; + + /* loop through all ports on this connection */ + + num_port = here->conn[ii]->size; + for(j = 0; j < num_port; j++) { + + /* if port is null, skip to next */ + if(here->conn[ii]->port[j]->is_null) + continue; + + /* determine the type of this output port */ + out_type = here->conn[ii]->port[j]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_out = &(here->conn[ii]->port[j]->smp_data); + + /* for this port, loop through all connections */ + /* and all ports to touch on each possible input */ + for(k = 0; k < num_conn; k++) { + + /* if the connection is null or is not an input */ + /* skip to next connection */ + if((here->conn[k]->is_null) || (! here->conn[k]->is_input)) + continue; + + num_port_k = here->conn[k]->size; + /* loop through all the ports of this connection */ + for(l = 0; l < num_port_k; l++) { + + /* if port is null, skip to next */ + if(here->conn[k]->port[l]->is_null) + continue; + + /* determine the type of this input port */ + in_type = here->conn[k]->port[l]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_cntl = &(here->conn[k]->port[l]->smp_data); + + /* determine type of controlled source according */ + /* to input and output types */ + cntl_src_type = MIFget_cntl_src_type(in_type, out_type); + + switch(cntl_src_type) { + case MIF_VCVS: + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(e.branch_poscntl, branch_poscntlBinding, branch, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(e.branch_negcntl, branch_negcntlBinding, branch, neg_node); + break; + case MIF_ICIS: + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(f.pos_ibranchcntl, pos_ibranchcntlBinding, pos_node, ibranch); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(f.neg_ibranchcntl, neg_ibranchcntlBinding, neg_node, ibranch); + break; + case MIF_VCIS: + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(g.pos_poscntl, pos_poscntlBinding, pos_node, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(g.pos_negcntl, pos_negcntlBinding, pos_node, neg_node); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(g.neg_poscntl, neg_poscntlBinding, neg_node, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(g.neg_negcntl, neg_negcntlBinding, neg_node, neg_node); + break; + case MIF_ICVS: + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX_XSPICE_INPUTS(h.branch_ibranchcntl, branch_ibranchcntlBinding, branch, ibranch); + break; + case MIF_minus_one: + break; + } /* end switch on controlled source type */ + } /* end for number of input ports */ + } /* end for number of input connections */ + } /* end for number of output ports */ + } /* end for number of output connections */ + } + } + + return (OK) ; +} + +int +MIFbindCSCComplexToReal (GENmodel *inModel, CKTcircuit *ckt) +{ + MIFmodel *model = (MIFmodel *)inModel ; + MIFinstance *here ; + int ii, j, k, l, num_conn, num_port, num_port_k ; + Mif_Boolean_t is_input, is_output ; + Mif_Cntl_Src_Type_t cntl_src_type ; + Mif_Port_Type_t in_type, out_type, type ; + Mif_Smp_Ptr_t *smp_data_cntl, *smp_data_out ; + + NG_IGNORE (ckt) ; + + /* loop through all the MIF models */ + for ( ; model != NULL ; model = MIFnextModel(model)) + { + /* loop through all the instances of the model */ + for (here = MIFinstances(model); here != NULL ; here = MIFnextInstance(here)) + { + /* Skip these expensive allocations if the instance is not analog */ + if(! here->analog) + continue; + + num_conn = here->num_conn; + + /* loop through all connections on this instance */ + /* and create matrix data needed for outputs and */ + /* V sources associated with I inputs */ + for(ii = 0; ii < num_conn; ii++) { + + /* if the connection is null, skip to next connection */ + if(here->conn[ii]->is_null) + continue; + + /* prepare things for convenient access later */ + is_input = here->conn[ii]->is_input; + is_output = here->conn[ii]->is_output; + num_port = here->conn[ii]->size; + + /* loop through all ports on this connection */ + for(j = 0; j < num_port; j++) { + + /* if port is null, skip to next */ + if(here->conn[ii]->port[j]->is_null) + continue; + + /* determine the type of this port */ + type = here->conn[ii]->port[j]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_out = &(here->conn[ii]->port[j]->smp_data); + + /* if it has a voltage source output, */ + /* create the matrix data needed */ + if( (is_output && (type == MIF_VOLTAGE || type == MIF_DIFF_VOLTAGE)) || + (type == MIF_RESISTANCE || type == MIF_DIFF_RESISTANCE) ) { + + /* then make the matrix pointers */ + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(pos_branch, pos_branchBinding, pos_node, branch); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(neg_branch, neg_branchBinding, neg_node, branch); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(branch_pos, branch_posBinding, branch, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(branch_neg, branch_negBinding, branch, neg_node); + } /* end if current input */ + + /* if it is a current input */ + /* create the matrix data needed for the associated zero-valued V source */ + if(is_input && (type == MIF_CURRENT || type == MIF_DIFF_CURRENT)) { + + /* then make the matrix pointers */ + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(pos_ibranch, pos_ibranchBinding, pos_node, ibranch); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(neg_ibranch, neg_ibranchBinding, neg_node, ibranch); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(ibranch_pos, ibranch_posBinding, ibranch, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_OUTPUTS(ibranch_neg, ibranch_negBinding, ibranch, neg_node); + } /* end if current input */ + } /* end for number of ports */ + } /* end for number of connections */ + + /* now loop through all connections on the instance and create */ + /* matrix data needed for partial derivatives of outputs */ + for(ii = 0; ii < num_conn; ii++) { + + /* if the connection is null or is not an output */ + /* skip to next connection */ + if((here->conn[ii]->is_null) || (! here->conn[ii]->is_output)) + continue; + + /* loop through all ports on this connection */ + + num_port = here->conn[ii]->size; + for(j = 0; j < num_port; j++) { + + /* if port is null, skip to next */ + if(here->conn[ii]->port[j]->is_null) + continue; + + /* determine the type of this output port */ + out_type = here->conn[ii]->port[j]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_out = &(here->conn[ii]->port[j]->smp_data); + + /* for this port, loop through all connections */ + /* and all ports to touch on each possible input */ + for(k = 0; k < num_conn; k++) { + + /* if the connection is null or is not an input */ + /* skip to next connection */ + if((here->conn[k]->is_null) || (! here->conn[k]->is_input)) + continue; + + num_port_k = here->conn[k]->size; + /* loop through all the ports of this connection */ + for(l = 0; l < num_port_k; l++) { + + /* if port is null, skip to next */ + if(here->conn[k]->port[l]->is_null) + continue; + + /* determine the type of this input port */ + in_type = here->conn[k]->port[l]->type; + + /* create a pointer to the smp data for quick access */ + smp_data_cntl = &(here->conn[k]->port[l]->smp_data); + + /* determine type of controlled source according */ + /* to input and output types */ + cntl_src_type = MIFget_cntl_src_type(in_type, out_type); + + switch(cntl_src_type) { + case MIF_VCVS: + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(e.branch_poscntl, branch_poscntlBinding, branch, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(e.branch_negcntl, branch_negcntlBinding, branch, neg_node); + break; + case MIF_ICIS: + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(f.pos_ibranchcntl, pos_ibranchcntlBinding, pos_node, ibranch); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(f.neg_ibranchcntl, neg_ibranchcntlBinding, neg_node, ibranch); + break; + case MIF_VCIS: + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(g.pos_poscntl, pos_poscntlBinding, pos_node, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(g.pos_negcntl, pos_negcntlBinding, pos_node, neg_node); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(g.neg_poscntl, neg_poscntlBinding, neg_node, pos_node); + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(g.neg_negcntl, neg_negcntlBinding, neg_node, neg_node); + break; + case MIF_ICVS: + CONVERT_KLU_BINDING_TABLE_TO_REAL_XSPICE_INPUTS(h.branch_ibranchcntl, branch_ibranchcntlBinding, branch, ibranch); + break; + case MIF_minus_one: + break; + } /* end switch on controlled source type */ + } /* end for number of input ports */ + } /* end for number of input connections */ + } /* end for number of output ports */ + } /* end for number of output connections */ + } + } + + return (OK) ; +} diff --git a/src/xspice/xspice.c b/src/xspice/xspice.c index 620981b91..4fe1cc597 100644 --- a/src/xspice/xspice.c +++ b/src/xspice/xspice.c @@ -83,4 +83,10 @@ struct coreInfo_t coreInfo = GC_realloc, no_free #endif +#ifdef KLU + , + MIFbindCSC, + MIFbindCSCComplex, + MIFbindCSCComplexToReal +#endif };