First attempt of KLU support for XSPICE
This commit is contained in:
parent
6b6642fbcf
commit
534394c0bb
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -91,4 +91,10 @@ struct coreInfo_t coreInfo =
|
|||
GC_realloc,
|
||||
no_free
|
||||
#endif
|
||||
#ifdef KLU
|
||||
,
|
||||
MIFbindCSC,
|
||||
MIFbindCSCComplex,
|
||||
MIFbindCSCComplexToReal
|
||||
#endif
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <stdlib.h>
|
||||
|
||||
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) ;
|
||||
}
|
||||
|
|
@ -83,4 +83,10 @@ struct coreInfo_t coreInfo =
|
|||
GC_realloc,
|
||||
no_free
|
||||
#endif
|
||||
#ifdef KLU
|
||||
,
|
||||
MIFbindCSC,
|
||||
MIFbindCSCComplex,
|
||||
MIFbindCSCComplexToReal
|
||||
#endif
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue