First attempt of KLU support for XSPICE
This commit is contained in:
parent
6b6642fbcf
commit
534394c0bb
|
|
@ -6,6 +6,7 @@
|
||||||
#ifndef ngspice_DLLITF_H
|
#ifndef ngspice_DLLITF_H
|
||||||
#define ngspice_DLLITF_H
|
#define ngspice_DLLITF_H
|
||||||
|
|
||||||
|
#include "ngspice/config.h"
|
||||||
#include "ngspice/mifproto.h"
|
#include "ngspice/mifproto.h"
|
||||||
#include "ngspice/cmproto.h"
|
#include "ngspice/cmproto.h"
|
||||||
|
|
||||||
|
|
@ -82,6 +83,12 @@ struct coreInfo_t {
|
||||||
void * ((*dllitf_tmalloc)(size_t));
|
void * ((*dllitf_tmalloc)(size_t));
|
||||||
void * ((*dllitf_trealloc)(const void *, size_t));
|
void * ((*dllitf_trealloc)(const void *, size_t));
|
||||||
void ((*dllitf_txfree)(const void *));
|
void ((*dllitf_txfree)(const void *));
|
||||||
|
|
||||||
|
#ifdef KLU
|
||||||
|
int ((*dllitf_MIFbindCSC) (GENmodel *, CKTcircuit *)) ;
|
||||||
|
int ((*dllitf_MIFbindCSCComplex) (GENmodel *, CKTcircuit *)) ;
|
||||||
|
int ((*dllitf_MIFbindCSCComplexToReal) (GENmodel *, CKTcircuit *)) ;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,38 @@
|
||||||
if ((here->a != 0) && (here->b != 0)) \
|
if ((here->a != 0) && (here->b != 0)) \
|
||||||
here->ptr = here->binding->CSC ;
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@ NON-STANDARD FEATURES
|
||||||
#include "ngspice/gendefs.h"
|
#include "ngspice/gendefs.h"
|
||||||
#include "ngspice/ifsim.h"
|
#include "ngspice/ifsim.h"
|
||||||
|
|
||||||
|
#ifdef KLU
|
||||||
|
#include "ngspice/smpdefs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The per-instance data structure */
|
/* The per-instance data structure */
|
||||||
|
|
||||||
|
|
@ -85,6 +88,26 @@ struct MIFinstance {
|
||||||
int inst_index; /* Index into inst_table in evt struct in ckt */
|
int inst_index; /* Index into inst_table in evt struct in ckt */
|
||||||
Mif_Callback_t callback; /* instance callback function */
|
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 *);
|
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
|
#ifndef CM_IGNORE
|
||||||
#define CM_IGNORE(x) (void) (x)
|
#define CM_IGNORE(x) (void) (x)
|
||||||
|
|
|
||||||
|
|
@ -91,4 +91,10 @@ struct coreInfo_t coreInfo =
|
||||||
GC_realloc,
|
GC_realloc,
|
||||||
no_free
|
no_free
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef KLU
|
||||||
|
,
|
||||||
|
MIFbindCSC,
|
||||||
|
MIFbindCSCComplex,
|
||||||
|
MIFbindCSCComplexToReal
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1040,6 +1040,12 @@ static int write_SPICEdev(
|
||||||
" .DEVdump = NULL,\n"
|
" .DEVdump = NULL,\n"
|
||||||
" .DEVacct = NULL,\n"
|
" .DEVacct = NULL,\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
"#ifdef KLU\n"
|
||||||
|
" .DEVbindCSC = MIFbindCSC,\n"
|
||||||
|
" .DEVbindCSCComplex = MIFbindCSCComplex,\n"
|
||||||
|
" .DEVbindCSCComplexToReal = MIFbindCSCComplexToReal,\n"
|
||||||
|
"#endif\n"
|
||||||
"};\n\n"
|
"};\n\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -430,6 +430,19 @@ void txfree(const void *ptr) {
|
||||||
(coreitf->dllitf_txfree)(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()
|
fopen_with_path()
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ libmifxsp_la_SOURCES = \
|
||||||
mifdestr.c \
|
mifdestr.c \
|
||||||
mif.c
|
mif.c
|
||||||
|
|
||||||
|
if KLU_WANTED
|
||||||
|
libmifxsp_la_SOURCES += mifbindCSC.c
|
||||||
|
endif
|
||||||
|
|
||||||
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
|
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
|
||||||
AM_CFLAGS = $(STATIC)
|
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,
|
GC_realloc,
|
||||||
no_free
|
no_free
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef KLU
|
||||||
|
,
|
||||||
|
MIFbindCSC,
|
||||||
|
MIFbindCSCComplex,
|
||||||
|
MIFbindCSCComplexToReal
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue