Skip to content

Commit

Permalink
integrate OSDI with KLU
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalkuthe authored and holvo committed Aug 16, 2023
1 parent c6b363f commit 499634d
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 11 deletions.
4 changes: 2 additions & 2 deletions compile_linux_klu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ if test "$1" = "d"; then
if [ $? -ne 0 ]; then echo "cd debug failed"; exit 1 ; fi
echo "configuring for 64 bit debug"
echo
../configure --with-x --enable-cider --with-readline=yes --enable-openmp --enable-xspice --enable-klu CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable" LDFLAGS="-m64 -g"
../configure --with-x --enable-cider --with-readline=yes --enable-openmp --enable-xspice --enable-klu --enable-predictor --enable-osdi CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable" LDFLAGS="-m64 -g"
else
cd release
if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi
echo "configuring for 64 bit release"
echo
../configure --with-x --enable-cider --with-readline=yes --enable-openmp --enable-xspice --enable-klu --disable-debug CFLAGS="-m64 -O2" LDFLAGS="-m64 -s"
../configure --with-x --enable-cider --with-readline=yes --enable-openmp --enable-xspice --enable-klu --enable-predictor --enable-osdi --disable-debug CFLAGS="-m64 -O2" LDFLAGS="-m64 -s"
fi
if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi

Expand Down
7 changes: 7 additions & 0 deletions src/include/ngspice/osdiitf.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#pragma once

#include "ngspice/config.h"
#include "ngspice/devdefs.h"
#include <stdint.h>

Expand All @@ -19,7 +20,13 @@ typedef struct OsdiRegistryEntry {
uint32_t inst_offset;
uint32_t dt;
uint32_t temp;

bool has_m;

#ifdef KLU
uint32_t matrix_ptr_offset;
#endif

} OsdiRegistryEntry;

typedef struct OsdiObjectFile {
Expand Down
12 changes: 9 additions & 3 deletions src/osdi/osdidefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,15 @@ typedef struct OsdiModelData {
} OsdiModelData;

extern size_t osdi_instance_data_off(const OsdiRegistryEntry *entry);
extern void *osdi_instance_data(const OsdiRegistryEntry *entry, GENinstance *inst);
extern OsdiExtraInstData *osdi_extra_instance_data(const OsdiRegistryEntry *entry,
GENinstance *inst);
extern void *osdi_instance_data(const OsdiRegistryEntry *entry,
GENinstance *inst);
#ifdef KLU
extern size_t osdi_instance_matrix_ptr_off(const OsdiRegistryEntry *entry);
extern double **osdi_instance_matrix_ptr(const OsdiRegistryEntry *entry,
GENinstance *inst);
#endif
extern OsdiExtraInstData *
osdi_extra_instance_data(const OsdiRegistryEntry *entry, GENinstance *inst);
extern size_t osdi_model_data_off(void);
extern void *osdi_model_data(GENmodel *model);
extern void *osdi_model_data_from_inst(GENinstance *inst);
Expand Down
8 changes: 7 additions & 1 deletion src/osdi/osdiext.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ extern int OSDIload(GENmodel *, CKTcircuit *);
extern int OSDItemp(GENmodel *, CKTcircuit *);
extern int OSDIacLoad(GENmodel *, CKTcircuit *);
extern int OSDItrunc(GENmodel *, CKTcircuit *, double *);
extern int OSDIpzLoad(GENmodel*, CKTcircuit*, SPcomplex*);
extern int OSDIpzLoad(GENmodel *, CKTcircuit *, SPcomplex *);

#ifdef KLU
extern int OSDIbindCSC(GENmodel *inModel, CKTcircuit *ckt);
extern int OSDIbindCSCComplexToReal(GENmodel *inModel, CKTcircuit *ckt);
extern int OSDIbindCSCComplex(GENmodel *inModel, CKTcircuit *ckt);
#endif

/* extern int OSDIconvTest(GENmodel*,CKTcircuit*); */
/* extern int OSDImDelete(GENmodel*); */
Expand Down
6 changes: 6 additions & 0 deletions src/osdi/osdiinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,5 +197,11 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
OSDIinfo->DEVpzLoad = OSDIpzLoad;
OSDIinfo->DEVtrunc = OSDItrunc;

#ifdef KLU
OSDIinfo->DEVbindCSC = OSDIbindCSC;
OSDIinfo->DEVbindCSCComplex = OSDIbindCSCComplex;
OSDIinfo->DEVbindCSCComplexToReal = OSDIbindCSCComplexToReal;
#endif

return OSDIinfo;
}
41 changes: 36 additions & 5 deletions src/osdi/osdiregistry.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
* Author: Pascal Kuthe <[email protected]>
*/

#include "ngspice/config.h"
#include "ngspice/hash.h"
#include "ngspice/memory.h"
#include "ngspice/stringutil.h"
#include "osdidefs.h"

#include <stddef.h>
#include <sys/stat.h>

#include "osdi.h"
Expand Down Expand Up @@ -199,6 +201,13 @@ static char *resolve_input_path(const char *name) {
return NULL;
} /* end of function inp_pathresolve_at */

static size_t pad_to_align(size_t alignment, size_t size) {
size_t padding = alignment - size % alignment;
if (padding == alignment) {
return 0;
}
return padding + size;
}
/**
* Calculates the offset that the OSDI instance data has from the beginning of
* the instance data allocated by ngspice. This offset is non trivial because
Expand All @@ -209,13 +218,21 @@ static char *resolve_input_path(const char *name) {
static size_t calc_osdi_instance_data_off(const OsdiDescriptor *descr) {
size_t res = sizeof(GENinstance) /* generic data */
+ descr->num_terminals * sizeof(int);
size_t padding = sizeof(max_align_t) - res % sizeof(max_align_t);
if (padding == sizeof(max_align_t)) {
padding = 0;
}
return res + padding;
#ifdef KLU
res = pad_to_align(alignof(double *), res);
res += ((size_t)descr->num_jacobian_entries) * 2 * sizeof(double *);
#endif
return pad_to_align(alignof(max_align_t), res);
}

#ifdef KLU
static size_t calc_osdi_instance_matrix_off(const OsdiDescriptor *descr) {
size_t res = sizeof(GENinstance) /* generic data */
+ descr->num_terminals * sizeof(int);
return pad_to_align(alignof(double *), res);
}
#endif

#define INVALID_OBJECT \
(OsdiObjectFile) { .num_entries = -1 }

Expand Down Expand Up @@ -386,6 +403,11 @@ extern OsdiObjectFile load_object_file(const char *input) {
.dt = dt,
.temp = temp,
.has_m = has_m,

#ifdef KLU
.matrix_ptr_offset = (uint32_t)calc_osdi_instance_matrix_off(descr),
#endif

};
}

Expand All @@ -399,6 +421,15 @@ extern OsdiObjectFile load_object_file(const char *input) {
inline size_t osdi_instance_data_off(const OsdiRegistryEntry *entry) {
return entry->inst_offset;
}
#ifdef KLU
inline size_t osdi_instance_matrix_ptr_off(const OsdiRegistryEntry *entry) {
return entry->matrix_ptr_offset;
}
inline double **osdi_instance_matrix_ptr(const OsdiRegistryEntry *entry,
GENinstance *inst) {
return (double **)(((char *)inst) + osdi_instance_matrix_ptr_off(entry));
}
#endif

inline void *osdi_instance_data(const OsdiRegistryEntry *entry,
GENinstance *inst) {
Expand Down
121 changes: 121 additions & 0 deletions src/osdi/osdisetup.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*/

#include "ngspice/iferrmsg.h"
#include "ngspice/klu.h"
#include "ngspice/memory.h"
#include "ngspice/ngspice.h"
#include "ngspice/typedefs.h"
Expand Down Expand Up @@ -408,3 +409,123 @@ extern int OSDIunsetup(GENmodel *inModel, CKTcircuit *ckt) {
}
return (OK);
}
#ifdef KLU
#include "ngspice/klu-binding.h"
static int init_matrix_klu(SMPmatrix *matrix, const OsdiDescriptor *descr,
void *inst, double **inst_matrix_ptrs) {
BindElement tmp;
BindElement *matched;
BindElement *bindings = matrix->SMPkluMatrix->KLUmatrixBindStructCOO;
size_t nz = (size_t)matrix->SMPkluMatrix->KLUmatrixLinkedListNZ;
uint32_t *node_mapping =
(uint32_t *)(((char *)inst) + descr->node_mapping_offset);
double **jacobian_ptr_resist =
(double **)(((char *)inst) + descr->jacobian_ptr_resist_offset);

for (uint32_t i = 0; i < descr->num_jacobian_entries; i++) {
uint32_t equation = descr->jacobian_entries[i].nodes.node_1;
uint32_t unkown = descr->jacobian_entries[i].nodes.node_2;
equation = node_mapping[equation];
unkown = node_mapping[unkown];
if (equation != 0 && unkown != 0) {
tmp.COO = jacobian_ptr_resist[i];
tmp.CSC = NULL;
tmp.CSC_Complex = NULL;
matched = (BindElement *)bsearch(&tmp, bindings, nz, sizeof(BindElement),
BindCompare);
if (matched == NULL) {
printf("Ptr %p not found in BindStruct Table\n",
jacobian_ptr_resist[i]);
return (E_PANIC);
}
uint32_t react_off = descr->jacobian_entries[i].react_ptr_off;
// complex number for ac analysis
if (react_off != UINT32_MAX) {
double **jacobian_ptr_react = (double **)(((char *)inst) + react_off);
*jacobian_ptr_react = matched->CSC_Complex + 1;
}
jacobian_ptr_resist[i] = matched->CSC;
inst_matrix_ptrs[2 * i] = matched->CSC;
inst_matrix_ptrs[2 * i + 1] = matched->CSC_Complex;
}
}
return (OK);
}

static int update_matrix_klu(const OsdiDescriptor *descr, void *inst,
double **inst_matrix_ptrs, bool complex) {
uint32_t *node_mapping =
(uint32_t *)(((char *)inst) + descr->node_mapping_offset);
double **jacobian_ptr_resist =
(double **)(((char *)inst) + descr->jacobian_ptr_resist_offset);

for (uint32_t i = 0; i < descr->num_jacobian_entries; i++) {
uint32_t equation = descr->jacobian_entries[i].nodes.node_1;
uint32_t unkown = descr->jacobian_entries[i].nodes.node_2;
equation = node_mapping[equation];
unkown = node_mapping[unkown];
if (equation != 0 && unkown != 0) {
jacobian_ptr_resist[i] = inst_matrix_ptrs[2 * i + complex];
}
}
return (OK);
}

int OSDIbindCSC(GENmodel *inModel, CKTcircuit *ckt) {

OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel);
const OsdiDescriptor *descr = entry->descriptor;
GENmodel *gen_model;
GENinstance *gen_inst;

/* setup a temporary buffer */
uint32_t *node_ids = TMALLOC(uint32_t, descr->num_nodes);

for (gen_model = inModel; gen_model; gen_model = gen_model->GENnextModel) {
void *model = osdi_model_data(gen_model);
for (gen_inst = gen_model->GENinstances; gen_inst;
gen_inst = gen_inst->GENnextInstance) {
void *inst = osdi_instance_data(entry, gen_inst);
double **matrix_ptrs = osdi_instance_matrix_ptr(entry, gen_inst);
int err = init_matrix_klu(ckt->CKTmatrix, descr, inst, matrix_ptrs);
if (err != (OK)) {
return err;
}
}
}

return (OK);
}
int OSDIupdateCSC(GENmodel *inModel, CKTcircuit *ckt, bool complex) {

OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel);
const OsdiDescriptor *descr = entry->descriptor;
GENmodel *gen_model;
GENinstance *gen_inst;

/* setup a temporary buffer */
uint32_t *node_ids = TMALLOC(uint32_t, descr->num_nodes);

for (gen_model = inModel; gen_model; gen_model = gen_model->GENnextModel) {
void *model = osdi_model_data(gen_model);
for (gen_inst = gen_model->GENinstances; gen_inst;
gen_inst = gen_inst->GENnextInstance) {
void *inst = osdi_instance_data(entry, gen_inst);
double **matrix_ptrs = osdi_instance_matrix_ptr(entry, gen_inst);
int err = update_matrix_klu(descr, inst, matrix_ptrs, complex);
if (err != (OK)) {
return err;
}
}
}

return (OK);
}
int OSDIbindCSCComplexToReal(GENmodel *inModel, CKTcircuit *ckt) {
OSDIupdateCSC(inModel, ckt, false);
}

int OSDIbindCSCComplex(GENmodel *inModel, CKTcircuit *ckt) {
OSDIupdateCSC(inModel, ckt, true);
}
#endif

0 comments on commit 499634d

Please sign in to comment.