xspice/icm/table, introduce table2d/table3d

which allows to model devices based upon linear interpolation
This commit is contained in:
h_vogt 2015-12-20 15:17:46 +01:00 committed by rlar
parent 869c598589
commit 37fe5308d3
30 changed files with 2802 additions and 2 deletions

View File

@ -27,6 +27,7 @@ if $__flag = 0
@XSPICEINIT@ codemodel @pkglibdir@/digital.cm
@XSPICEINIT@ codemodel @pkglibdir@/xtradev.cm
@XSPICEINIT@ codemodel @pkglibdir@/xtraevt.cm
@XSPICEINIT@ codemodel @pkglibdir@/table.cm
end
unset __flag

View File

@ -15,7 +15,7 @@ dist-hook:
rm -rf `find $(distdir)/icm -name .deps`
rm -rf `find $(distdir)/icm -name *.o`
rm -rf `find $(distdir)/icm -name *.cm`
for sub in analog digital spice2poly xtradev xtraevt ; do \
for sub in analog digital spice2poly xtradev xtraevt table ; do \
rm -rf `find $(distdir)/icm/$$sub -name cmextrn.h`; \
rm -rf `find $(distdir)/icm/$$sub -name cminfo.h`; \
rm -rf `find $(distdir)/icm/$$sub -name udnextrn.h`; \

View File

@ -7,7 +7,7 @@ include makedefs
# The codemodels to make
CMDIRS = spice2poly digital analog xtradev xtraevt
CMDIRS = spice2poly digital analog xtradev xtraevt table
all:

View File

@ -0,0 +1,71 @@
/* Convenience allocation programs. */
/*
Copyright (C) 2004 University of Texas at Austin
Copyright (C) 2007 Colorado School of Mines
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <sys/types.h>
#include "alloc.h"
#include "ngspice/cm.h"
/*------------------------------------------------------------*/
void *
sf_alloc(int n /* number of elements */,
size_t size /* size of one element */)
/*< output-checking allocation >*/
{
void *ptr;
size *= (size_t) n;
if (0 >= size)
cm_message_printf("%s: illegal allocation(%d bytes)", __FILE__, (int) size);
ptr = malloc(size);
if (NULL == ptr)
cm_message_printf("%s: cannot allocate %d bytes : ", __FILE__, (int) size);
return ptr;
}
/*------------------------------------------------------------*/
double *
sf_doublealloc(int n /* number of elements */)
/*< float allocation >*/
{
return (double*) sf_alloc(n, sizeof(double));
}
/*------------------------------------------------------------*/
double **
sf_doublealloc2(int n1 /* fast dimension */,
int n2 /* slow dimension */)
/*< float 2-D allocation, out[0] points to a contiguous array >*/
{
int i2;
double **ptr = (double**) sf_alloc(n2, sizeof(double*));
ptr[0] = sf_doublealloc(n1 * n2);
for (i2 = 1; i2 < n2; i2++)
ptr[i2] = ptr[0] + i2 * n1;
return ptr;
}

View File

@ -0,0 +1,23 @@
#ifndef _sf_alloc_h
#define _sf_alloc_h
#include <stdio.h>
#include <stdlib.h>
/*------------------------------------------------------------*/
void *sf_alloc (int n, /* number of elements */
size_t size /* size of one element */);
/*< output-checking allocation >*/
/*------------------------------------------------------------*/
double *sf_doublealloc (int n /* number of elements */);
/*< double allocation >*/
/*------------------------------------------------------------*/
double **sf_doublealloc2(int n1, /* fast dimension */
int n2 /* slow dimension */);
/*< float 2-D allocation, out[0] points to a contiguous array >*/
#endif

View File

@ -0,0 +1,133 @@
/* 1-D ENO interpolation */
/*
Copyright (C) 2004 University of Texas at Austin
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <math.h>
#include <float.h>
#include <stdlib.h>
#include "eno.h"
#include "alloc.h"
#define SF_MAX(a,b) ((a) < (b) ? (b) : (a))
#define SF_MIN(a,b) ((a) < (b) ? (a) : (b))
struct Eno {
int order, n;
double **diff;
};
/* concrete data type */
sf_eno
sf_eno_init (int order, /* interpolation order */
int n /* data size */)
/*< Initialize interpolation object. >*/
{
sf_eno ent;
int i;
ent = (sf_eno) sf_alloc(1, sizeof(*ent));
ent->order = order;
ent->n = n;
ent->diff = (double**) sf_alloc(order, sizeof(double*));
for (i = 0; i < order; i++)
ent->diff[i] = sf_doublealloc(n - i);
return ent;
}
void
sf_eno_close (sf_eno ent)
/*< Free internal storage >*/
{
int i;
for (i = 0; i < ent->order; i++)
free (ent->diff[i]);
free (ent->diff);
free (ent);
}
void
sf_eno_set (sf_eno ent, double *c /* data [n] */)
/*< Set the interpolation table. c can be changed or freed afterwords >*/
{
int i, j;
for (i = 0; i < ent->n; i++) {
/* copy the initial data */
ent->diff[0][i] = c[i];
}
for (j = 1; j < ent->order; j++) {
for (i = 0; i < ent->n - j; i++) {
/* compute difference tables */
ent->diff[j][i] = ent->diff[j - 1][i + 1] - ent->diff[j - 1][i];
}
}
}
void sf_eno_apply (sf_eno ent,
int i, /* grid location */
double x, /* offset from grid */
double *f, /* output data value */
double *f1, /* output derivative */
der what /* flag of what to compute */)
/*< Apply interpolation >*/
{
int j, k, i1, i2, n;
double s, s1, y, w, g, g1;
i2 = SF_MAX (0, SF_MIN(i, ent->n - ent->order));
i1 = SF_MIN (i2, SF_MAX(0, i - ent->order + 2));
w = fabs(ent->diff[ent->order - 1][i1]);
for (j = i1 + 1; j <= i2; j++) {
g = fabs(ent->diff[ent->order - 1][j]);
if (w > g)
w = g;
}
/* loop over starting points */
for (g = 0., g1 = 0., n = 0, j = i1; j <= i2; j++) {
if (fabs(ent->diff[ent->order - 1][j]) > w)
continue;
n++;
y = x + i - j;
/* loop to compute the polynomial */
for (s = 1., s1 = 0., k = 0; k < ent->order; k++) {
if (what != FUNC) {
g1 += s1 * ent->diff[k][j];
s1 = (s + s1 * (y - k)) / (k + 1.);
}
if (what != DER)
g += s * ent->diff[k][j];
s *= (y - k) / (k + 1.);
}
}
if (what != DER)
*f = g / n;
if (what != FUNC)
*f1 = g1 / n;
}
/* $Id: eno.c 8699 2012-07-03 22:10:38Z vovizmus $ */

View File

@ -0,0 +1,36 @@
/* This file is automatically generated. DO NOT EDIT! */
#ifndef _sf_eno_h
#define _sf_eno_h
typedef struct Eno *sf_eno;
/* abstract data type */
typedef enum {FUNC, DER, BOTH} der;
/* flag values */
sf_eno sf_eno_init (int order, /* interpolation order */
int n /* data size */);
/*< Initialize interpolation object. >*/
void sf_eno_close (sf_eno ent);
/*< Free internal storage >*/
void sf_eno_set (sf_eno ent, double* c /* data [n] */);
/*< Set the interpolation table. c can be changed or freed afterwords >*/
void sf_eno_apply (sf_eno ent,
int i, /* grid location */
double x, /* offset from grid */
double *f, /* output data value */
double *f1, /* output derivative */
der what /* flag of what to compute */);
/*< Apply interpolation >*/
#endif

View File

@ -0,0 +1,120 @@
/* ENO interpolation in 2-D */
/*
Copyright (C) 2004 University of Texas at Austin
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "eno.h"
#include "eno2.h"
#include "alloc.h"
#include "ngspice/cm.h"
struct Eno2 {
int order, ng, n1, n2;
sf_eno jnt, *ent;
double *f, *f1;
};
/* concrete data type */
sf_eno2
sf_eno2_init (int order, /* interpolation order */
int n1, int n2 /* data dimensions */)
/*< Initialize interpolation object >*/
{
sf_eno2 pnt;
int i2;
pnt = (sf_eno2) sf_alloc(1, sizeof(*pnt));
pnt->order = order;
pnt->n1 = n1;
pnt->n2 = n2;
pnt->ng = 2 * order - 2;
if (pnt->ng > pnt->n2)
cm_message_printf("%s: ng=%d is too big", __FILE__, pnt->ng);
pnt->jnt = sf_eno_init (order, pnt->ng);
pnt->f = sf_doublealloc (pnt->ng);
pnt->f1 = sf_doublealloc (pnt->ng);
pnt->ent = (sf_eno*) sf_alloc(n2, sizeof(sf_eno));
for (i2 = 0; i2 < n2; i2++)
pnt->ent[i2] = sf_eno_init (order, n1);
return pnt;
}
void
sf_eno2_set (sf_eno2 pnt, double **c /* data [n2][n1] */)
/*< Set the interpolation table. c can be changed or freed afterwords. >*/
{
int i2;
for (i2 = 0; i2 < pnt->n2; i2++)
sf_eno_set (pnt->ent[i2], c[i2]);
}
void
sf_eno2_close (sf_eno2 pnt)
/*< Free internal storage >*/
{
int i2;
sf_eno_close (pnt->jnt);
for (i2 = 0; i2 < pnt->n2; i2++)
sf_eno_close (pnt->ent[i2]);
free (pnt->f);
free (pnt->f1);
free (pnt->ent);
free (pnt);
}
void
sf_eno2_apply (sf_eno2 pnt,
int i, int j, /* grid location */
double x, double y, /* offset from grid */
double *f, /* output data value */
double *f1, /* output derivative [2] */
der what /* what to compute [FUNC,DER,BOTH] */)
/*< Apply interpolation. >*/
{
int k, b2;
double g;
if (j - pnt->order + 2 < 0)
b2 = 0;
else if (j + pnt->order - 1 > pnt->n2 - 1)
b2 = pnt->n2 - pnt->ng;
else
b2 = j - pnt->order + 2;
j -= b2;
for (k = 0; k < pnt->ng; k++)
if (what != FUNC)
sf_eno_apply (pnt->ent[b2 + k], i, x, pnt->f + k, pnt->f1 + k, BOTH);
else
sf_eno_apply (pnt->ent[b2 + k], i, x, pnt->f + k, pnt->f1 + k, FUNC);
sf_eno_set (pnt->jnt, pnt->f);
sf_eno_apply (pnt->jnt, j, y, f, f1 + 1, what);
if (what != FUNC) {
sf_eno_set (pnt->jnt, pnt->f1);
sf_eno_apply (pnt->jnt, j, y, f1, &g, FUNC);
}
}
/* $Id: eno2.c 9044 2012-08-13 19:35:59Z vovizmus $ */

View File

@ -0,0 +1,35 @@
/* This file is automatically generated. DO NOT EDIT! */
#ifndef _sf_eno2_h
#define _sf_eno2_h
#include "eno.h"
typedef struct Eno2 *sf_eno2;
/* abstract data type */
sf_eno2 sf_eno2_init (int order, /* interpolation order */
int n1, int n2 /* data dimensions */);
/*< Initialize interpolation object >*/
void sf_eno2_set (sf_eno2 pnt, double **c /* data [n2][n1] */);
/*< Set the interpolation table. c can be changed or freed afterwords. >*/
void sf_eno2_close (sf_eno2 pnt);
/*< Free internal storage >*/
void sf_eno2_apply (sf_eno2 pnt,
int i, int j, /* grid location */
double x, double y, /* offset from grid */
double *f, /* output data value */
double *f1, /* output derivative [2] */
der what /* what to compute [FUNC,DER,BOTH] */);
/*< Apply interpolation. >*/
#endif

View File

@ -0,0 +1,142 @@
/* ENO interpolation in 3-D */
/*
Copyright (C) 2004 University of Texas at Austin
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "eno2.h"
#include "eno3.h"
#include "alloc.h"
#include "ngspice/cm.h"
struct Eno3 {
int order, ng, n1, n2, n3;
sf_eno **ent;
sf_eno2 jnt;
double **f, **f1;
};
/* concrete data type */
sf_eno3
sf_eno3_init(int order, /* interpolation order */
int n1, int n2, int n3 /* data dimensions */)
/*< Initialize interpolation object >*/
{
sf_eno3 pnt;
int i2, i3;
pnt = (sf_eno3) sf_alloc (1, sizeof(*pnt));
pnt->order = order;
pnt->n1 = n1;
pnt->n2 = n2;
pnt->n3 = n3;
pnt->ng = 2 * order - 2;
if (pnt->ng > n2 || pnt->ng > n3)
cm_message_printf("%s: ng=%d is too big", __FILE__, pnt->ng);
pnt->jnt = sf_eno2_init (order, pnt->ng, pnt->ng);
pnt->f = sf_doublealloc2 (pnt->ng, pnt->ng);
pnt->f1 = sf_doublealloc2 (pnt->ng, pnt->ng);
pnt->ent = (sf_eno**) sf_alloc (n3, sizeof(sf_eno*));
for (i3 = 0; i3 < n3; i3++) {
pnt->ent[i3] = (sf_eno*) sf_alloc (n2, sizeof(sf_eno));
for (i2 = 0; i2 < n2; i2++)
pnt->ent[i3][i2] = sf_eno_init (order, n1);
}
return pnt;
}
void
sf_eno3_set(sf_eno3 pnt, double ***c /* data [n3][n2][n1] */)
/*< Set the interpolation table. c can be changed or freed afterwords. >*/
{
int i2, i3;
for (i3 = 0; i3 < pnt->n3; i3++)
for (i2 = 0; i2 < pnt->n2; i2++)
sf_eno_set (pnt->ent[i3][i2], c[i3][i2]);
}
void
sf_eno3_close(sf_eno3 pnt)
/*< Free internal storage. >*/
{
int i2, i3;
sf_eno2_close (pnt->jnt);
for (i3 = 0; i3 < pnt->n3; i3++) {
for (i2 = 0; i2 < pnt->n2; i2++)
sf_eno_close (pnt->ent[i3][i2]);
free (pnt->ent[i3]);
}
free (pnt->ent);
free (pnt->f[0]);
free (pnt->f);
free (pnt->f1[0]);
free (pnt->f1);
free (pnt);
}
void
sf_eno3_apply(sf_eno3 pnt,
int i, int j, int k, /* grid location */
double x, double y, double z, /* offsets from grid */
double *f, /* output data */
double *f1, /* output derivative [3] */
der what /* to compute [FUNC|DER|BOTH] */)
/*< Apply interpolation. >*/
{
int i2, i3, b2, b3;
double g;
if (j - pnt->order + 2 < 0)
b2 = 0;
else if (j + pnt->order - 1 > pnt->n2 - 1)
b2 = pnt->n2 - pnt->ng;
else
b2 = j - pnt->order + 2;
j -= b2;
if (k - pnt->order + 2 < 0)
b3 = 0;
else if (k + pnt->order - 1 > pnt->n3 - 1)
b3 = pnt->n3 - pnt->ng;
else
b3 = k - pnt->order + 2;
k -= b3;
for (i3 = 0; i3 < pnt->ng; i3++)
for (i2 = 0; i2 < pnt->ng; i2++)
sf_eno_apply (pnt->ent[b3 + i3][b2 + i2], i, x,
&(pnt->f[i3][i2]),
&(pnt->f1[i3][i2]),
(what==FUNC ? FUNC : BOTH));
sf_eno2_set (pnt->jnt, pnt->f);
sf_eno2_apply (pnt->jnt, j, k, y, z, f, f1 + 1, what);
if (what != FUNC) {
sf_eno2_set (pnt->jnt, pnt->f1);
sf_eno2_apply (pnt->jnt, j, k, y, z, f1, &g, FUNC);
}
}
/* $Id: eno3.c 4148 2009-02-09 03:55:32Z sfomel $ */

View File

@ -0,0 +1,35 @@
/* This file is automatically generated. DO NOT EDIT! */
#ifndef _sf_eno3_h
#define _sf_eno3_h
#include "eno2.h"
typedef struct Eno3 *sf_eno3;
/* abstract data type */
sf_eno3 sf_eno3_init (int order, /* interpolation order */
int n1, int n2, int n3 /* data dimensions */);
/*< Initialize interpolation object >*/
void sf_eno3_set (sf_eno3 pnt, double ***c /* data [n3][n2][n1] */);
/*< Set the interpolation table. c can be changed or freed afterwords. >*/
void sf_eno3_close (sf_eno3 pnt);
/*< Free internal storage. >*/
void sf_eno3_apply (sf_eno3 pnt,
int i, int j, int k, /* grid location */
double x, double y, double z, /* offsets from grid */
double *f, /* output data */
double *f1, /* output derivative [3] */
der what /* to compute [FUNC|DER|BOTH] */);
/*< Apply interpolation. >*/
#endif

View File

@ -0,0 +1,2 @@
table2D
table3D

View File

@ -0,0 +1,135 @@
/*=== Static CNVgettok ROUTINE ================*/
/*
Get the next token from the input string. The input string pointer
is advanced to the following token and the token from the input
string is copied to malloced storage and a pointer to that storage
is returned. The original input string is undisturbed.
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/*=== CONSTANTS ========================*/
#define OK 0
#define FAIL 1
/* Type definition for each possible token returned. */
typedef enum token_type_s { CNV_NO_TOK, CNV_STRING_TOK } Cnv_Token_Type_t;
extern char *CNVget_token(char **s, Cnv_Token_Type_t *type);
/*=== MACROS ===========================*/
#if defined(__MINGW32__) || defined(_MSC_VER)
#define DIR_PATHSEP "\\"
#else
#define DIR_PATHSEP "/"
#endif
#if defined(_MSC_VER)
#define strdup _strdup
#define snprintf _snprintf
#endif
char *
CNVgettok(char **s)
{
char *buf; /* temporary storage to copy token into */
/*char *temp;*/ /* temporary storage to copy token into */
char *ret_str; /* storage for returned string */
int i;
/* allocate space big enough for the whole string */
buf = (char *) malloc(strlen(*s) + 1);
/* skip over any white space */
while (isspace_c(**s) || (**s == '=') ||
(**s == '(') || (**s == ')') || (**s == ','))
(*s)++;
/* isolate the next token */
switch (**s) {
case '\0': /* End of string found */
if (buf)
free(buf);
return NULL;
default: /* Otherwise, we are dealing with a */
/* string representation of a number */
/* or a mess o' characters. */
i = 0;
while ( (**s != '\0') &&
(! ( isspace_c(**s) || (**s == '=') ||
(**s == '(') || (**s == ')') ||
(**s == ',')
) ) ) {
buf[i] = **s;
i++;
(*s)++;
}
buf[i] = '\0';
break;
}
/* skip over white space up to next token */
while (isspace_c(**s) || (**s == '=') ||
(**s == '(') || (**s == ')') || (**s == ','))
(*s)++;
/* make a copy using only the space needed by the string length */
ret_str = (char *) malloc(strlen(buf) + 1);
ret_str = strcpy(ret_str,buf);
if (buf) free(buf);
return ret_str;
}
/*=== Static CNVget_token ROUTINE =============*/
/*
Get the next token from the input string together with its type.
The input string pointer
is advanced to the following token and the token from the input
string is copied to malloced storage and a pointer to that storage
is returned. The original input string is undisturbed.
*/
char *
CNVget_token(char **s, Cnv_Token_Type_t *type)
{
char *ret_str; /* storage for returned string */
/* get the token from the input line */
ret_str = CNVgettok(s);
/* if no next token, return */
if (ret_str == NULL) {
*type = CNV_NO_TOK;
return NULL;
}
/* else, determine and return token type */
switch (*ret_str) {
default:
*type = CNV_STRING_TOK;
break;
}
return ret_str;
}

View File

@ -0,0 +1,183 @@
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/*********************/
/* 3d geometry types */
/*********************/
typedef struct Point3Struct { /* 3d point */
double x, y, z;
} Point3;
typedef Point3 Vector3;
//FIXME
double BilinearInterpolation(double q11, double q12, double q21, double q22, double x1, double x2, double y1, double y2, double x, double y);
/* Function to find the cross over point (the point before
which elements are smaller than or equal to x and after
which greater than x)
http://www.geeksforgeeks.org/find-k-closest-elements-given-value/ */
int
findCrossOver(double arr[], int low, int high, double x)
{
int mid;
// Base cases
if (arr[high] <= x) // x is greater than all
return high;
if (arr[low] > x) // x is smaller than all
return low;
// Find the middle point
mid = (low + high)/2; /* low + (high - low)/2 */
/* If x is same as middle element, then return mid */
if (arr[mid] <= x && arr[mid+1] > x)
return mid;
/* If x is greater than arr[mid], then either arr[mid + 1]
is ceiling of x or ceiling lies in arr[mid+1...high] */
if (arr[mid] < x)
return findCrossOver(arr, mid+1, high, x);
return findCrossOver(arr, low, mid - 1, x);
}
/* https://helloacm.com/cc-function-to-compute-the-bilinear-interpolation/ */
double
BilinearInterpolation(double q11, double q12, double q21, double q22, double x1, double x2, double y1, double y2, double x, double y)
{
double x2x1, y2y1, x2x, y2y, yy1, xx1;
x2x1 = x2 - x1;
y2y1 = y2 - y1;
x2x = x2 - x;
y2y = y2 - y;
yy1 = y - y1;
xx1 = x - x1;
return 1.0 / (x2x1 * y2y1) * (
q11 * x2x * y2y +
q21 * xx1 * y2y +
q12 * x2x * yy1 +
q22 * xx1 * yy1
);
}
/*
* C code from the article
* "Tri-linear Interpolation"
* by Steve Hill, sah@ukc.ac.uk
* in "Graphics Gems IV", Academic Press, 1994
*
*/
#if 0
double
trilinear(Point3 *p, double *d, int xsize, int ysize, int zsize, double def)
{
# define DENS(X, Y, Z) d[(X)+xsize*((Y)+ysize*(Z))]
int x0, y0, z0,
x1, y1, z1;
double *dp,
fx, fy, fz,
d000, d001, d010, d011,
d100, d101, d110, d111,
dx00, dx01, dx10, dx11,
dxy0, dxy1, dxyz;
x0 = floor(p->x);
fx = p->x - x0;
y0 = floor(p->y);
fy = p->y - y0;
z0 = floor(p->z);
fz = p->z - z0;
x1 = x0 + 1;
y1 = y0 + 1;
z1 = z0 + 1;
if (x0 >= 0 && x1 < xsize &&
y0 >= 0 && y1 < ysize &&
z0 >= 0 && z1 < zsize) {
dp = &DENS(x0, y0, z0);
d000 = dp[0];
d100 = dp[1];
dp += xsize;
d010 = dp[0];
d110 = dp[1];
dp += xsize*ysize;
d011 = dp[0];
d111 = dp[1];
dp -= xsize;
d001 = dp[0];
d101 = dp[1];
} else {
# define INRANGE(X, Y, Z) \
((X) >= 0 && (X) < xsize && \
(Y) >= 0 && (Y) < ysize && \
(Z) >= 0 && (Z) < zsize)
d000 = INRANGE(x0, y0, z0) ? DENS(x0, y0, z0) : def;
d001 = INRANGE(x0, y0, z1) ? DENS(x0, y0, z1) : def;
d010 = INRANGE(x0, y1, z0) ? DENS(x0, y1, z0) : def;
d011 = INRANGE(x0, y1, z1) ? DENS(x0, y1, z1) : def;
d100 = INRANGE(x1, y0, z0) ? DENS(x1, y0, z0) : def;
d101 = INRANGE(x1, y0, z1) ? DENS(x1, y0, z1) : def;
d110 = INRANGE(x1, y1, z0) ? DENS(x1, y1, z0) : def;
d111 = INRANGE(x1, y1, z1) ? DENS(x1, y1, z1) : def;
}
/* linear interpolation from l (when a=0) to h (when a=1)*/
/* (equal to (a*h)+((1-a)*l) */
#define LERP(a,l,h) ((l)+(((h)-(l))*(a)))
dx00 = LERP(fx, d000, d100);
dx01 = LERP(fx, d001, d101);
dx10 = LERP(fx, d010, d110);
dx11 = LERP(fx, d011, d111);
dxy0 = LERP(fy, dx00, dx10);
dxy1 = LERP(fy, dx01, dx11);
dxyz = LERP(fz, dxy0, dxy1);
return dxyz;
}
#endif
/* trilinear interpolation
Paul Bourke
July 1997
http://paulbourke.net/miscellaneous/interpolation/ */
double
TrilinearInterpolation(double x, double y, double z, int xind, int yind, int zind, double ***td)
{
double V000, V100, V010, V001, V101, V011, V110, V111, Vxyz;
V000 = td[zind][yind][xind];
V100 = td[zind][yind][xind+1];
V010 = td[zind][yind+1][xind];
V001 = td[zind+1][yind][xind];
V101 = td[zind+1][yind][xind+1];
V011 = td[zind+1][yind+1][xind];
V110 = td[zind][yind+1][xind+1];
V111 = td[zind+1][yind+1][xind+1];
Vxyz = V000 * (1 - x) * (1 - y) * (1 - z) +
V100 * x * (1 - y) * (1 - z) +
V010 * (1 - x) * y * (1 - z) +
V001 * (1 - x) * (1 - y) * z +
V101 * x * (1 - y) * z +
V011 * (1 - x) * y * z +
V110 * x * y * (1 - z) +
V111 * x * y * z;
return Vxyz;
}

View File

@ -0,0 +1,705 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
FILE table2D/cfunc.mod
Copyright 2015
Holger Vogt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
AUTHORS
03 Nov 2015 Holger Vogt
MODIFICATIONS
SUMMARY
This file contains the model-specific routines used to
functionally describe the 2D table code model used
to read and interpolate a value from a 2D table from a file.
The essentially non-oscillatory (ENO) interpolation in 2-D (eno2.c) is taken from the
Madagascar Project at http://www.ahay.org/wiki/Main_Page
Currently ENO is used only to obtain the derivatives,
the data values are obtained by bilinear interpolation.
This combination allows op convergence for some data tables (no guarantee though).
INTERFACES
FILE ROUTINE CALLED
N/A N/A
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
===============================================================================*/
/*=== INCLUDE FILES ====================*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "mada/eno2.h"
/*=== CONSTANTS ========================*/
#define OK 0
#define FAIL 1
/*=== MACROS ===========================*/
#if defined(__MINGW32__) || defined(_MSC_VER)
#define DIR_PATHSEP "\\"
#else
#define DIR_PATHSEP "/"
#endif
#if defined(_MSC_VER)
#define strdup _strdup
#define snprintf _snprintf
#endif
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
struct filesource_state {
FILE *fp;
long pos;
unsigned char atend;
};
typedef struct {
int ix; /* size of array in x */
int iy; /* size of array in y */
struct filesource_state *state; /* the storage array for the
filesource status. */
int init_err;
sf_eno2 newtable; /* the table, code borrowed from madagascar project */
double *xcol; /* array of floats in x */
double *ycol; /* array of floats in y */
double **table;
} Local_Data_t;
/* Type definition for each possible token returned. */
typedef enum token_type_s {CNV_NO_TOK, CNV_STRING_TOK} Cnv_Token_Type_t;
typedef char line_t[82]; /* A SPICE size line. <= 80 characters plus '\n\0' */
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
extern int findCrossOver(double arr[], int low, int high, double x);
extern double BilinearInterpolation(double q11, double q12, double q21, double q22, double x1, double x2, double y1, double y2, double x, double y);
extern char *CNVgettok(char **s);
/*==============================================================================
FUNCTION cnv_get_spice_value()
AUTHORS
??? Bill Kuhn
MODIFICATIONS
30 Sep 1991 Jeffrey P. Murray
SUMMARY
This function takes as input a string token from a SPICE
deck and returns a floating point equivalent value.
INTERFACES
FILE ROUTINE CALLED
N/A N/A
RETURNED VALUE
Returns the floating point value in pointer *p_value. Also
returns an integer representing successful completion.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
NONE
==============================================================================*/
/*=== Static CNV_get_spice_value ROUTINE =============*/
/*
Function takes as input a string token from a SPICE
deck and returns a floating point equivalent value.
*/
static int
cnv_get_spice_value(char *str, /* IN - The value text e.g. 1.2K */
double *p_value) /* OUT - The numerical value */
{
/* the following were "int4" devices - jpm */
size_t len;
size_t i;
int n_matched;
line_t val_str;
char c = ' ';
char c1;
double scale_factor;
double value;
/* Scan the input string looking for an alpha character that is not */
/* 'e' or 'E'. Such a character is assumed to be an engineering */
/* suffix as defined in the Spice 2G.6 user's manual. */
len = strlen(str);
if (len > sizeof(val_str) - 1)
len = sizeof(val_str) - 1;
for (i = 0; i < len; i++) {
c = str[i];
if (isalpha_c(c) && (c != 'E') && (c != 'e'))
break;
else if (isspace_c(c))
break;
else
val_str[i] = c;
}
val_str[i] = '\0';
/* Determine the scale factor */
if ((i >= len) || !isalpha_c(c))
scale_factor = 1.0;
else {
if (isupper_c(c))
c = tolower_c(c);
switch (c) {
case 't':
scale_factor = 1.0e12;
break;
case 'g':
scale_factor = 1.0e9;
break;
case 'k':
scale_factor = 1.0e3;
break;
case 'u':
scale_factor = 1.0e-6;
break;
case 'n':
scale_factor = 1.0e-9;
break;
case 'p':
scale_factor = 1.0e-12;
break;
case 'f':
scale_factor = 1.0e-15;
break;
case 'm':
i++;
if (i >= len) {
scale_factor = 1.0e-3;
break;
}
c1 = str[i];
if (!isalpha_c(c1)) {
scale_factor = 1.0e-3;
break;
}
if (islower_c(c1))
c1 = toupper_c(c1);
if (c1 == 'E')
scale_factor = 1.0e6;
else if (c1 == 'I')
scale_factor = 25.4e-6;
else
scale_factor = 1.0e-3;
break;
default:
scale_factor = 1.0;
}
}
/* Convert the numeric portion to a float and multiply by the */
/* scale factor. */
n_matched = sscanf(val_str, "%le", &value);
if (n_matched < 1) {
*p_value = 0.0;
return FAIL;
}
*p_value = value * scale_factor;
return OK;
}
/*==============================================================================
FUNCTION void cm_table2D()
AUTHORS
08 Nov 2015 Holger Vogt
MODIFICATIONS
SUMMARY
This function implements 2D table code model.
INTERFACES
FILE ROUTINE CALLED
N/A N/A
RETURNED VALUE
Returns inputs and outputs via ARGS structure.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
NONE
INPUT FILE SPEC
* Title (comments preceded by * ignored)
* table size
ix
iy
* x row independent variables
x0 x1 x2 x3 ... xix-1
y column independent variables
y0 y1 y2 y3 ... yiy-1
* table
x0y0 x1y0 x2y0 ... xix-1y0
...
x0yiy-1 x1yiy-1 x2yiy-1 ... xix-1yiy-1
==============================================================================*/
/*=== CM_table2D ROUTINE ===*/
void
cm_table2D(ARGS) /* structure holding parms, inputs, outputs, etc. */
{
int size, xind, yind;
double xval, yval, xoff, yoff, xdiff, ydiff;
double derivval[2], outval;
double q11, q12, q21, q22, x1, x2, y1, y2;
Local_Data_t *loc; /* Pointer to local static data, not to be included
in the state vector */
Mif_Complex_t ac_gain;
size = PORT_SIZE(out);
if (INIT == 1) {
int i;
int ix = 0, /* elements in a row */
iy = 0; /* number of rows */
double **table_data;
double tmp;
char *cFile, *cThisPtr, *cThisLine, *cThisLinePtr;
int isNewline; /* Boolean indicating we've read a CR or LF */
size_t lFileLen; /* Length of file */
size_t lFileRead; /* Length of file read in */
long lIndex; /* Index into cThisLine array */
int lLineCount; /* Current line number */
size_t lStartPos; /* Offset of start of current line */
size_t lTotalChars; /* Total characters read */
int interporder; /* order of interpolation for eno */
/* allocate static storage for *loc */
STATIC_VAR (locdata) = calloc(1, sizeof(Local_Data_t));
loc = STATIC_VAR (locdata);
/* Allocate storage for internal state */
loc->state = (struct filesource_state*) malloc(sizeof(struct filesource_state));
loc->ix = loc->iy = 0;
/* open file */
loc->state->fp = fopen_with_path(PARAM(file), "r");
loc->state->pos = 0;
loc->state->atend = 0;
if (!loc->state->fp) {
char *lbuffer, *p;
lbuffer = getenv("NGSPICE_INPUT_DIR");
if (lbuffer && *lbuffer) {
p = (char*) malloc(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(PARAM(file)) + 1);
sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file));
loc->state->fp = fopen(p, "r");
free(p);
}
}
struct stat st;
if (!loc->state->fp || fstat(fileno(loc->state->fp), &st)) {
cm_message_printf("cannot open file %s", PARAM(file));
loc->state->atend = 1;
loc->init_err = 1;
return;
}
/* get file length */
lFileLen = (size_t) st.st_size;
/* create string to hold the whole file */
cFile = calloc(lFileLen + 1, sizeof(char));
/* create another string long enough for file manipulation */
cThisLine = calloc(lFileLen + 1, sizeof(char));
if (cFile == NULL || cThisLine == NULL) {
cm_message_printf("Insufficient memory to read file %s", PARAM(file));
loc->state->atend = 1;
loc->init_err = 1;
return;
}
/* read whole file into cFile */
lFileRead = fread(cFile, sizeof(char), lFileLen, loc->state->fp);
fclose(loc->state->fp);
/* Number of chars read may be less than lFileLen, because /r are skipt by 'fread' */
cFile[lFileRead] = '\0';
cThisPtr = cFile;
cThisLinePtr = cThisLine;
lLineCount = 0L;
lTotalChars = 0L;
while (*cThisPtr) { /* Read until reaching null char */
lIndex = 0L; /* Reset counters and flags */
isNewline = 0;
lStartPos = lTotalChars;
while (*cThisPtr) {
if (!isNewline) { /* Haven't read a LF yet */
if (*cThisPtr == '\n') /* This char is LF */
isNewline = 1; /* Set flag */
}
else if (*cThisPtr != '\n') /* Already found LF */
break; /* Done with line */
cThisLinePtr[lIndex++] = *cThisPtr++; /* Add char to output and increment */
lTotalChars++;
}
cThisLinePtr[lIndex] = '\0'; /* Terminate the string */
lLineCount++; /* Increment the line counter */
/* continue if comment or empty */
if (cThisLinePtr[0] == '*' || cThisLinePtr[0] == '\n') {
lLineCount--; /* we count only real lines */
continue;
}
if (lLineCount == 1) {
cnv_get_spice_value(cThisLinePtr, &tmp);
loc->ix = ix = (int) tmp;
/* generate row data structure (x) */
loc->xcol = (double*) calloc((size_t) ix, sizeof(double));
}
else if (lLineCount == 2) {
cnv_get_spice_value(cThisLinePtr, &tmp);
loc->iy = iy = (int) tmp;
/* generate column data structure (y) */
loc->ycol = (double*) calloc((size_t) iy, sizeof(double));
}
else if (lLineCount == 3) {
char *token = CNVgettok(&cThisLinePtr);
i = 0;
while (token) {
if (i == ix) {
cm_message_printf("Too many numbers in x row.");
loc->init_err = 1;
return;
}
cnv_get_spice_value(token, &loc->xcol[i++]);
free(token);
token = CNVgettok(&cThisLinePtr);
}
if (i < ix) {
cm_message_printf("Not enough numbers in x row.");
loc->init_err = 1;
return;
}
}
else if (lLineCount == 4) {
char *token = CNVgettok(&cThisLinePtr);
i = 0;
while (token) {
if (i == iy) {
cm_message_printf("Too many numbers in y row.");
loc->init_err = 1;
return;
}
cnv_get_spice_value(token, &loc->ycol[i++]);
free(token);
token = CNVgettok(&cThisLinePtr);
}
if (i < iy) {
cm_message_printf("Not enough numbers in y row.");
loc->init_err = 1;
return;
}
/* jump out of while loop to read in the table */
break;
}
}
/* generate table core */
interporder = PARAM(order);
/* boundary limits set to param 'order' aren't recognized,
so limit them here */
if (interporder < 2) {
cm_message_printf("Parameter Order=%d not possible, set to minimum value 2", interporder);
interporder = 2;
}
/* int order : interpolation order,
int n1, int n2 : data dimensions */
loc->newtable = sf_eno2_init(interporder, ix, iy);
/* create table_data in memory */
/* data [n2][n1] */
table_data = calloc((size_t) iy, sizeof(double *));
for (i = 0; i < iy; i++)
table_data[i] = calloc((size_t) ix, sizeof(double));
loc->table = table_data;
/* continue reading from cFile */
lLineCount = 0;
while (*cThisPtr) { /* Read until reaching null char */
char *token;
lIndex = 0L; /* Reset counters and flags */
isNewline = 0;
lStartPos = lTotalChars;
while (*cThisPtr) { /* Read until reaching null char */
if (!isNewline) { /* Haven't read a LF yet */
if (*cThisPtr == '\n') /* This char is a LF */
isNewline = 1; /* Set flag */
}
else if (*cThisPtr != '\n') /* Already found LF */
break; /* Done with line */
cThisLinePtr[lIndex++] = *cThisPtr++; /* Add char to output and increment */
lTotalChars++;
}
cThisLinePtr[lIndex] = '\0'; /* Terminate the string */
lLineCount++; /* Increment the line counter */
/* continue if comment or empty */
if (cThisLinePtr[0] == '*' || cThisLinePtr[0] == '\0') {
if (lTotalChars >= lFileLen) {
cm_message_printf("Not enough data in file %s", PARAM(file));
loc->init_err = 1;
return;
}
lLineCount--; /* we count only real lines */
continue;
}
token = CNVgettok(&cThisLinePtr);
i = 0;
while (token) {
double tmpval;
if (i == ix) {
cm_message_printf("Too many numbers in y row no. %d.", lLineCount);
loc->init_err = 1;
return;
}
/* read table core from cFile, fill local static table structure table_data */
cnv_get_spice_value(token, &tmpval);
table_data[lLineCount - 1][i++] = tmpval;
free(token);
token = CNVgettok(&cThisLinePtr);
}
if (i < ix) {
cm_message_printf("Not enough numbers in y row no. %d.", lLineCount);
loc->init_err = 1;
return;
}
}
/* fill table data into eno2 structure */
sf_eno2_set (loc->newtable, table_data /* data [n2][n1] */);
/* free all the emory allocated */
// for (i = 0; i < iy; i++)
// free(table_data[i]);
// free(table_data);
free(cFile);
free(cThisLine);
} /* end of initialization "if (INIT == 1)" */
loc = STATIC_VAR (locdata);
/* return immediately if there was an initialization error */
if (loc->init_err == 1)
return;
/* get input x, y,
find corresponding indices,
get x and y offsets,
call interpolation function with value and derivative */
xval = INPUT(inx);
yval = INPUT(iny);
/* find index */
if (xval < loc->xcol[0] || xval > loc->xcol[loc->ix - 1]) {
if (PARAM(verbose) > 0)
cm_message_printf("x value %g exceeds table limits,\n"
" please enlarge range of your table",
xval);
return;
}
if (yval < loc->ycol[0] || yval > loc->ycol[loc->iy - 1]) {
if (PARAM(verbose) > 0)
cm_message_printf("y value %g exceeds table limits,\n"
" please enlarge range of your table",
yval);
return;
}
/* something like binary search to get the index */
xind = findCrossOver(loc->xcol, 0, loc->ix - 1, xval);
/* find index with minimum distance between xval and row value */
if (fabs(loc->xcol[xind + 1] - xval) < fabs(xval - loc->xcol[xind]))
xind++;
xoff = xval - loc->xcol[xind];
yind = findCrossOver(loc->ycol, 0, loc->iy - 1, yval);
/* find index with minimum distance between yval and column value */
if (fabs(loc->ycol[yind + 1] - yval) < fabs(yval - loc->ycol[yind]))
yind++;
yoff = yval - loc->ycol[yind];
/* find local difference around index of independent row and column values */
if (xind == loc->ix - 1)
xdiff = loc->xcol[xind] - loc->xcol[xind - 1];
else if (xind == 0)
xdiff = loc->xcol[xind + 1] - loc->xcol[xind];
else
xdiff = 0.5 * (loc->xcol[xind + 1] - loc->xcol[xind - 1]);
if (yind == loc->iy - 1)
ydiff = loc->ycol[yind] - loc->ycol[yind - 1];
else if (yind == 0)
ydiff = loc->ycol[yind + 1] - loc->ycol[yind];
else
ydiff = 0.5 * (loc->ycol[yind + 1] - loc->ycol[yind - 1]);
/* Essentially non-oscillatory (ENO) interpolation to obtain the derivatives only.
Using outval for now yields ngspice op non-convergence */
sf_eno2_apply (loc->newtable,
xind, yind, /* grid location */
xoff, yoff, /* offset from grid */
&outval, /* output data value */
derivval, /* output derivatives [2] */
DER /* what to compute [FUNC, DER, BOTH] */
);
/* bilinear interpolation to obtain the output value */
xind = findCrossOver(loc->xcol, 0, loc->ix - 1, xval);
yind = findCrossOver(loc->ycol, 0, loc->iy - 1, yval);
x1 = loc->xcol[xind];
x2 = loc->xcol[xind + 1];
y1 = loc->ycol[yind];
y2 = loc->ycol[yind + 1];
q11 = loc->table[yind][xind];
q12 = loc->table[yind + 1][xind];
q21 = loc->table[yind][xind + 1];
q22 = loc->table[yind + 1][xind + 1];
outval = BilinearInterpolation(q11, q12, q21, q22, x1, x2, y1, y2, xval, yval);
if (ANALYSIS != MIF_AC) {
double xderiv, yderiv, outv;
outv = PARAM(offset) + PARAM(gain) * outval;
OUTPUT(out) = outv;
xderiv = PARAM(gain) * derivval[0] / xdiff;
PARTIAL(out, inx) = xderiv;
yderiv = PARAM(gain) * derivval[1] / ydiff;
PARTIAL(out, iny) = yderiv;
if (PARAM(verbose) > 1)
cm_message_printf("\nI: %g, xval: %g, yval: %g, xderiv: %g, yderiv: %g", outv, xval, yval, xderiv, yderiv);
}
else {
ac_gain.real = PARAM(gain) * derivval[0] / xdiff;
ac_gain.imag= 0.0;
AC_GAIN(out, inx) = ac_gain;
ac_gain.real = PARAM(gain) * derivval[1] / ydiff;
ac_gain.imag= 0.0;
AC_GAIN(out, iny) = ac_gain;
}
}

View File

@ -0,0 +1,78 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
Copyright 2015
Holger Vogt
AUTHORS
06 Nov 2015 Holger Vogt
SUMMARY
This file contains the interface specification file for the
2D table code model.
===============================================================================*/
NAME_TABLE:
C_Function_Name: cm_table2D
Spice_Model_Name: table2d
Description: "2D table model"
PORT_TABLE:
Port_Name: inx iny out
Description: "inputx" "inputy" "output"
Direction: in in out
Default_Type: v v i
Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id,vnam] [v,vd,i,id]
Vector: no no no
Vector_Bounds: - - -
Null_Allowed: no no no
PARAMETER_TABLE:
Parameter_Name: order verbose
Description: "order" "verbose"
Data_Type: int int
Default_Value: 3 0
Limits: [2 -] [0 2]
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: offset gain
Description: "offset" "gain"
Data_Type: real real
Default_Value: 0.0 1.0
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: file
Description: "file name"
Data_Type: string
Default_Value: "2D-table-model.txt"
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
STATIC_VAR_TABLE:
Static_Var_Name: locdata
Description: "local static data"
Data_Type: pointer

View File

@ -0,0 +1,768 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
FILE table3D/cfunc.mod
Copyright 2015
Holger Vogt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
AUTHORS
03 Nov 2015 Holger Vogt
MODIFICATIONS
SUMMARY
This file contains the model-specific routines used to
functionally describe the 3D table code model used
to read and interpolate a value from a 3D table from a file.
The essentially non-oscillatory (ENO) interpolation in 3-D (eno3.c) is taken from the
Madagascar Project at http://www.ahay.org/wiki/Main_Page
Currently ENO is used only to obtain the derivatives,
the data values are obtained by trilinear interpolation.
This combination allows op convergence for some data tables (no guarantee though).
INTERFACES
FILE ROUTINE CALLED
N/A N/A
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
===============================================================================*/
/*=== INCLUDE FILES ====================*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "mada/eno2.h"
#include "mada/eno3.h"
/*=== CONSTANTS ========================*/
#define OK 0
#define FAIL 1
/*=== MACROS ===========================*/
#if defined(__MINGW32__) || defined(_MSC_VER)
#define DIR_PATHSEP "\\"
#else
#define DIR_PATHSEP "/"
#endif
#if defined(_MSC_VER)
#define strdup _strdup
#define snprintf _snprintf
#endif
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
struct filesource_state {
FILE *fp;
long pos;
unsigned char atend;
};
typedef struct {
int ix; /* size of array in x */
int iy; /* size of array in y */
int iz; /* size of array in z */
struct filesource_state *state; /* the storage array for the
filesource status. */
int init_err;
sf_eno3 newtable; /* the table, code borrowed from madagascar project */
double *xcol; /* array of doubles in x */
double *ycol; /* array of doubles in y */
double *zcol; /* array of doubles in z */
double ***table;
} Local_Data_t;
/*********************/
/* 3d geometry types */
/*********************/
typedef char line_t[82]; /* A SPICE size line. <= 80 characters plus '\n\0' */
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
extern int findCrossOver(double arr[], int low, int high, double x);
extern double TrilinearInterpolation(double x, double y, double z, int xind, int yind, int zind, double ***td);
extern char *CNVgettok(char **s);
/*==============================================================================
FUNCTION cnv_get_spice_value()
AUTHORS
??? Bill Kuhn
MODIFICATIONS
30 Sep 1991 Jeffrey P. Murray
SUMMARY
This function takes as input a string token from a SPICE
deck and returns a floating point equivalent value.
INTERFACES
FILE ROUTINE CALLED
N/A N/A
RETURNED VALUE
Returns the floating point value in pointer *p_value. Also
returns an integer representing successful completion.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
NONE
==============================================================================*/
/*=== Static CNV_get_spice_value ROUTINE =============*/
/*
Function takes as input a string token from a SPICE
deck and returns a floating point equivalent value.
*/
static int
cnv_get_spice_value(char *str, /* IN - The value text e.g. 1.2K */
double *p_value) /* OUT - The numerical value */
{
/* the following were "int4" devices - jpm */
size_t len;
size_t i;
int n_matched;
line_t val_str;
char c = ' ';
char c1;
double scale_factor;
double value;
/* Scan the input string looking for an alpha character that is not */
/* 'e' or 'E'. Such a character is assumed to be an engineering */
/* suffix as defined in the Spice 2G.6 user's manual. */
len = strlen(str);
if (len > sizeof(val_str) - 1)
len = sizeof(val_str) - 1;
for (i = 0; i < len; i++) {
c = str[i];
if (isalpha_c(c) && (c != 'E') && (c != 'e'))
break;
else if (isspace_c(c))
break;
else
val_str[i] = c;
}
val_str[i] = '\0';
/* Determine the scale factor */
if ((i >= len) || (! isalpha_c(c)))
scale_factor = 1.0;
else {
if (isupper_c(c))
c = tolower_c(c);
switch (c) {
case 't':
scale_factor = 1.0e12;
break;
case 'g':
scale_factor = 1.0e9;
break;
case 'k':
scale_factor = 1.0e3;
break;
case 'u':
scale_factor = 1.0e-6;
break;
case 'n':
scale_factor = 1.0e-9;
break;
case 'p':
scale_factor = 1.0e-12;
break;
case 'f':
scale_factor = 1.0e-15;
break;
case 'm':
i++;
if (i >= len) {
scale_factor = 1.0e-3;
break;
}
c1 = str[i];
if (!isalpha_c(c1)) {
scale_factor = 1.0e-3;
break;
}
if (islower_c(c1))
c1 = toupper_c(c1);
if (c1 == 'E')
scale_factor = 1.0e6;
else if (c1 == 'I')
scale_factor = 25.4e-6;
else
scale_factor = 1.0e-3;
break;
default:
scale_factor = 1.0;
}
}
/* Convert the numeric portion to a float and multiply by the */
/* scale factor. */
n_matched = sscanf(val_str, "%le", &value);
if (n_matched < 1) {
*p_value = 0.0;
return FAIL;
}
*p_value = value * scale_factor;
return OK;
}
/*==============================================================================
FUNCTION void cm_table3D()
AUTHORS
08 Nov 2015 Holger Vogt
MODIFICATIONS
SUMMARY
This function implements 2D table code model.
INTERFACES
FILE ROUTINE CALLED
N/A N/A
RETURNED VALUE
Returns inputs and outputs via ARGS structure.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
NONE
INPUT FILE SPEC
* Title (comments preceded by * ignored)
* table size
ix
iy
* x row independent variables
x0 x1 x2 x3 ... xix-1
y column independent variables
y0 y1 y2 y3 ... yiy-1
* table
x0y0 x1y0 x2y0 ... xix-1y0
...
x0yiy-1 x1yiy-1 x2yiy-1 ... xix-1yiy-1
==============================================================================*/
/*=== CM_table3D ROUTINE ===*/
void
cm_table3D(ARGS) /* structure holding parms, inputs, outputs, etc. */
{
int size, xind, yind, zind;
double xval, yval, zval, xoff, yoff, zoff, xdiff, ydiff, zdiff;
double derivval[3], outval;
Local_Data_t *loc; /* Pointer to local static data, not to be included
in the state vector */
Mif_Complex_t ac_gain;
size = PORT_SIZE(out);
if (INIT == 1) {
int i, j;
int ix = 0, /* elements in a row */
iy = 0, /* number of rows */
iz = 0; /* number of 2D tables */
double ***table_data;
double tmp;
char *cFile, *cThisPtr, *cThisLine, *cThisLinePtr;
int isNewline; /* Boolean indicating we've read a CR or LF */
size_t lFileLen; /* Length of file */
size_t lFileRead; /* Length of file read in */
long lIndex; /* Index into cThisLine array */
int lLineCount; /* Current line number */
size_t lStartPos; /* Offset of start of current line */
size_t lTotalChars; /* Total characters read */
int lTableCount; /* Number of tables */
int interporder; /* order of interpolation for eno */
/* allocate static storage for *loc */
STATIC_VAR (locdata) = calloc (1, sizeof(Local_Data_t));
loc = STATIC_VAR (locdata);
/* Allocate storage for internal state */
loc->state = (struct filesource_state*) malloc(sizeof(struct filesource_state));
loc->ix = loc->iy = loc->iz = 0;
loc->init_err = 0;
/* open file */
loc->state->fp = fopen_with_path(PARAM(file), "r");
loc->state->pos = 0;
loc->state->atend = 0;
if (!loc->state->fp) {
char *lbuffer, *pp;
lbuffer = getenv("NGSPICE_INPUT_DIR");
if (lbuffer && *lbuffer) {
pp = (char*) malloc(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(PARAM(file)) + 1);
sprintf(pp, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file));
loc->state->fp = fopen(pp, "r");
free(pp);
}
}
struct stat st;
if (!loc->state->fp || fstat(fileno(loc->state->fp), &st)) {
cm_message_printf("cannot open file %s", PARAM(file));
loc->state->atend = 1;
loc->init_err = 1;
return;
}
/* get file length */
lFileLen = (size_t) st.st_size;
/* create string to hold the whole file */
cFile = calloc(lFileLen + 1, sizeof(char));
/* create another string long enough for file manipulation */
cThisLine = calloc(lFileLen + 1, sizeof(char));
if (cFile == NULL || cThisLine == NULL) {
cm_message_printf("Insufficient memory to read file %s", PARAM(file));
loc->state->atend = 1;
loc->init_err = 1;
return;
}
/* read whole file into cFile */
lFileRead = fread(cFile, sizeof(char), lFileLen, loc->state->fp);
fclose(loc->state->fp);
/* Number of chars read may be less than lFileLen, because /r are skipt by 'fread' */
cFile[lFileRead] = '\0';
cThisPtr = cFile;
cThisLinePtr = cThisLine;
lLineCount = 0L;
lTotalChars = 0L;
while (*cThisPtr) { /* Read until reaching null char */
lIndex = 0L; /* Reset counters and flags */
isNewline = 0;
lStartPos = lTotalChars;
while (*cThisPtr) { /* Read until reaching null char */
if (!isNewline) { /* Haven't read a LF yet */
if (*cThisPtr == '\n') /* This char is a LF */
isNewline = 1; /* Set flag */
}
else if (*cThisPtr != '\n') /* Already found LF */
break; /* Done with line */
cThisLinePtr[lIndex++] = *cThisPtr++; /* Add char to output and increment */
lTotalChars++;
}
cThisLinePtr[lIndex] = '\0'; /* Terminate the string */
lLineCount++; /* Increment the line counter */
/* continue if comment or empty */
if (cThisLinePtr[0] == '*' || cThisLinePtr[0] == '\n') {
lLineCount--; /* we count only real lines */
continue;
}
if (lLineCount == 1) {
cnv_get_spice_value(cThisLinePtr, &tmp);
loc->ix = ix = (int) tmp;
/* generate row data structure (x) */
loc->xcol = (double*) calloc((size_t) ix, sizeof(double));
} else if (lLineCount == 2) {
cnv_get_spice_value(cThisLinePtr, &tmp);
loc->iy = iy = (int) tmp;
/* generate column data structure (y) */
loc->ycol = (double*) calloc((size_t) iy, sizeof(double));
} else if (lLineCount == 3) {
cnv_get_spice_value(cThisLinePtr, &tmp);
loc->iz = iz = (int) tmp;
/* generate column data structure (y) */
loc->zcol = (double*) calloc((size_t) iz, sizeof(double));
} else if (lLineCount == 4) {
char *token = CNVgettok(&cThisLinePtr);
i = 0;
while (token) {
if (i == ix) {
cm_message_printf("Too many numbers in x row.");
loc->init_err = 1;
return;
}
cnv_get_spice_value(token, &loc->xcol[i++]);
free(token);
token = CNVgettok(&cThisLinePtr);
}
if (i < ix) {
cm_message_printf("Not enough numbers in x row.");
loc->init_err = 1;
return;
}
} else if (lLineCount == 5) {
char *token = CNVgettok(&cThisLinePtr);
i = 0;
while (token) {
if (i == iy) {
cm_message_printf("Too many numbers in y row.");
loc->init_err = 1;
return;
}
cnv_get_spice_value(token, &loc->ycol[i++]);
free(token);
token = CNVgettok(&cThisLinePtr);
}
if (i < iy) {
cm_message_printf("Not enough numbers in y row.");
loc->init_err = 1;
return;
}
} else if (lLineCount == 6) {
char *token = CNVgettok(&cThisLinePtr);
i = 0;
while (token) {
if (i == iz) {
cm_message_printf("Too many numbers in z row.");
loc->init_err = 1;
return;
}
cnv_get_spice_value(token, &loc->zcol[i++]);
free(token);
token = CNVgettok(&cThisLinePtr);
}
if (i < iz) {
cm_message_printf("Not enough numbers in z row.");
loc->init_err = 1;
return;
}
/* jump out of while loop to read in the table */
break;
}
}
/* generate table core */
interporder = PARAM(order);
/* boundary limits set to param 'order' aren't recognized,
so limit them here */
if (interporder < 2) {
cm_message_printf("Parameter Order=%d not possible, set to minimum value 2", interporder);
interporder = 2;
}
/* int order : interpolation order,
int n1, int n2, int n3 : data dimensions */
loc->newtable = sf_eno3_init(interporder, ix, iy, iz);
/* create table_data in memory */
/* data [n3][n2][n1] */
table_data = calloc((size_t) iy, sizeof(double *));
for (i = 0; i < iz; i++) {
table_data[i] = calloc((size_t) iy, sizeof(double *));
for (j = 0; j < iy; j++)
table_data[i][j] = calloc((size_t) ix, sizeof(double));
}
loc->table = table_data;
/* continue reading from cFile */
for (lTableCount = 0; lTableCount < iz; lTableCount++) {
lLineCount = 0;
while (lLineCount < iy) {
char *token;
lIndex = 0L; /* Reset counters and flags */
isNewline = 0;
lStartPos = lTotalChars;
/* read a line */
while (*cThisPtr) { /* Read until reaching null char */
if (!isNewline) { /* Haven't read a CR or LF yet */
if (*cThisPtr == '\n') /* This char is LF */
isNewline = 1; /* Set flag */
}
else if (*cThisPtr != '\n') /* Already found LF */
break; /* Done with line */
cThisLinePtr[lIndex++] = *cThisPtr++; /* Add char to output and increment */
lTotalChars++;
}
cThisLinePtr[lIndex] = '\0'; /* Terminate the string */
/* continue if comment or empty */
if (cThisLinePtr[0] == '*' || cThisLinePtr[0] == '\0') {
if (lTotalChars >= lFileLen) {
cm_message_printf("Not enough data in file %s", PARAM(file));
loc->init_err = 1;
return;
}
continue;
}
token = CNVgettok(&cThisLinePtr);
i = 0;
while (token) {
double tmpval;
if (i == ix) {
cm_message_printf("Too many numbers in y row no. %d of table %d.", lLineCount, lTableCount);
loc->init_err = 1;
return;
}
/* read table core from cFile, fill local static table structure table_data */
cnv_get_spice_value(token, &tmpval);
table_data[lTableCount][lLineCount][i++] = tmpval;
free(token);
token = CNVgettok(&cThisLinePtr);
}
if (i < ix) {
cm_message_printf("Not enough numbers in y row no. %d of table %d.", lLineCount, lTableCount);
loc->init_err = 1;
return;
}
lLineCount++;
}
}
/* fill table data into eno3 structure */
sf_eno3_set(loc->newtable, table_data /* data [n3][n2][n1] */);
/* free all the emory allocated */
// for (i = 0; i < iy; i++)
// free(table_data[i]);
// free(table_data);
free(cFile);
free(cThisLine);
} /* end of initialization "if (INIT == 1)" */
loc = STATIC_VAR (locdata);
/* return immediately if there was an initialization error */
if (loc->init_err == 1)
return;
/* get input x, y, z;
find corresponding indices;
get x and y offsets;
call interpolation functions with value and derivative */
xval = INPUT(inx);
yval = INPUT(iny);
zval = INPUT(inz);
/* check table ranges */
if (xval < loc->xcol[0] || xval > loc->xcol[loc->ix - 1]) {
if (PARAM(verbose) > 0)
cm_message_printf("x value %g exceeds table limits, \nplease enlarge range of your table", xval);
return;
}
if (yval < loc->ycol[0] || yval > loc->ycol[loc->iy - 1]) {
if (PARAM(verbose) > 0)
cm_message_printf("y value %g exceeds table limits, \nplease enlarge range of your table", yval);
return;
}
if (zval < loc->zcol[0] || zval > loc->zcol[loc->iz - 1]) {
if (PARAM(verbose) > 0)
cm_message_printf("z value %g exceeds table limits, \nplease enlarge range of your table", zval);
return;
}
/* find index */
/* something like binary search to get the index */
xind = findCrossOver(loc->xcol, 0, loc->ix - 1, xval);
/* find index with minimum distance between xval and row value
if (fabs(loc->xcol[xind + 1] - xval) < fabs(xval - loc->xcol[xind]))
xind++;
*/
xoff = xval - loc->xcol[xind];
yind = findCrossOver(loc->ycol, 0, loc->iy - 1, yval);
/* find index with minimum distance between yval and column value
if (fabs(loc->ycol[yind + 1] - yval) < fabs(yval - loc->ycol[yind]))
yind++;
*/
yoff = yval - loc->ycol[yind];
zind = findCrossOver(loc->zcol, 0, loc->iz - 1, zval);
/* find index with minimum distance between zval and table value
if (fabs(loc->zcol[zind + 1] - zval) < fabs(zval - loc->zcol[zind]))
zind++;
*/
zoff = zval - loc->zcol[zind];
/* find local difference around index of independent row and column values */
if (xind == loc->ix - 1)
xdiff = loc->xcol[xind] - loc->xcol[xind - 1];
else if (xind == 0)
xdiff = loc->xcol[xind + 1] - loc->xcol[xind];
else
xdiff = 0.5 * (loc->xcol[xind + 1] - loc->xcol[xind - 1]);
if (yind == loc->iy - 1)
ydiff = loc->ycol[yind] - loc->ycol[yind - 1];
else if (yind == 0)
ydiff = loc->ycol[yind + 1] - loc->ycol[yind];
else
ydiff = 0.5 * (loc->ycol[yind + 1] - loc->ycol[yind - 1]);
if (zind == loc->iz - 1)
zdiff = loc->zcol[zind] - loc->zcol[zind - 1];
else if (zind == 0)
zdiff = loc->zcol[zind + 1] - loc->zcol[zind];
else
zdiff = 0.5 * (loc->zcol[zind + 1] - loc->zcol[zind - 1]);
/* Essentially non-oscillatory (ENO) interpolation to obtain the derivatives only.
Using outval for now yields ngspice op non-convergence */
sf_eno3_apply (loc->newtable,
xind, yind, zind, /* grid location */
xoff, yoff, zoff, /* offset from grid */
&outval, /* output data value */
derivval, /* output derivatives [3] */
DER /* what to compute [FUNC, DER, BOTH] */
);
outval = TrilinearInterpolation(xoff / (loc->xcol[xind + 1] - loc->xcol[xind]),
yoff / (loc->ycol[yind + 1] - loc->ycol[yind]),
zoff / (loc->zcol[zind + 1] - loc->zcol[zind]),
xind, yind, zind, loc->table);
if (ANALYSIS != MIF_AC) {
double xderiv, yderiv, zderiv, outv;
outv = PARAM(offset) + PARAM(gain) * outval;
OUTPUT(out) = outv;
xderiv = PARAM(gain) * derivval[0] / xdiff;
PARTIAL(out, inx) = xderiv;
yderiv = PARAM(gain) * derivval[1] / ydiff;
PARTIAL(out, iny) = yderiv;
zderiv = PARAM(gain) * derivval[2] / zdiff;
PARTIAL(out, inz) = zderiv;
if (PARAM(verbose) > 1)
cm_message_printf("\nI: %g, xval: %g, yval: %g, zval: %g, xderiv: %g, yderiv: %g, zderiv: %g", outv, xval, yval, zval, xderiv, yderiv, zderiv);
} else {
ac_gain.real = PARAM(gain) * derivval[0] / xdiff;
ac_gain.imag= 0.0;
AC_GAIN(out, inx) = ac_gain;
ac_gain.real = PARAM(gain) * derivval[1] / ydiff;
ac_gain.imag= 0.0;
AC_GAIN(out, iny) = ac_gain;
}
}
/* These includes add functions from extra source code files,
* still using the standard XSPICE procedure of cmpp-ing cfunc.mod
* and then only compiling the resulting *.c file.
*/
#include "../support/gettokens.c" /* reading tokens */
#include "../support/interp.c" /* 2D and 3D linear interpolation */
#include "../mada/alloc.c" /* eno interpolation from madagascar project */
#include "../mada/eno.c" /* eno interpolation from madagascar project */
#include "../mada/eno2.c" /* eno interpolation from madagascar project */
#include "../mada/eno3.c" /* eno interpolation from madagascar project */

View File

@ -0,0 +1,87 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
Copyright 2015
Holger Vogt
AUTHORS
06 Nov 2015 Holger Vogt
SUMMARY
This file contains the interface specification file for the
3D table code model.
===============================================================================*/
NAME_TABLE:
C_Function_Name: cm_table3D
Spice_Model_Name: table3d
Description: "3D table model"
PORT_TABLE:
Port_Name: inx iny inz
Description: "inputx" "inputy" "inputz"
Direction: in in in
Default_Type: v v v
Allowed_Types: [v,vd,i,id,vnam] [v,vd,i,id,vnam] [v,vd,i,id,vnam]
Vector: no no no
Vector_Bounds: - - -
Null_Allowed: no no no
PORT_TABLE:
Port_Name: out
Description: "output"
Direction: out
Default_Type: i
Allowed_Types: [v,vd,i,id]
Vector: no
Vector_Bounds: -
Null_Allowed: no
PARAMETER_TABLE:
Parameter_Name: order verbose
Description: "order" "verbose"
Data_Type: int int
Default_Value: 3 0
Limits: [2 -] [0 2]
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: offset gain
Description: "offset" "gain"
Data_Type: real real
Default_Value: 0.0 1.0
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: file
Description: "file name"
Data_Type: string
Default_Value: "3D-table-model.txt"
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
STATIC_VAR_TABLE:
Static_Var_Name: locdata
Description: "local static data"
Data_Type: pointer

View File

View File

@ -42,6 +42,7 @@ C:\Spice\
spice2poly.cm
extradev.cm
extravt.cm
table.cm
share\
ngspice
scripts\

View File

@ -17,6 +17,7 @@ mkdir %dst%\share\ngspice\scripts
copy "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.OPENMP\vcomp140.dll" %dst%\bin\
copy %cmsrc%\analog.cm %dst%\lib\ngspice\analog.cm
copy %cmsrc%\digital.cm %dst%\lib\ngspice\digital.cm
copy %cmsrc%\table.cm %dst%\lib\ngspice\table.cm
copy %cmsrc%\xtraevt.cm %dst%\lib\ngspice\xtraevt.cm
copy %cmsrc%\xtradev.cm %dst%\lib\ngspice\xtradev.cm
copy %cmsrc%\spice2poly.cm %dst%\lib\ngspice\spice2poly.cm
@ -45,6 +46,7 @@ mkdir %dst%\share\ngspice\scripts
copy "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.OPENMP\vcomp140.dll" %dst%\bin\
copy %cmsrc%\analog64.cm %dst%\lib\ngspice\analog.cm
copy %cmsrc%\digital64.cm %dst%\lib\ngspice\digital.cm
copy %cmsrc%\table64.cm %dst%\lib\ngspice\table.cm
copy %cmsrc%\xtraevt64.cm %dst%\lib\ngspice\xtraevt.cm
copy %cmsrc%\xtradev64.cm %dst%\lib\ngspice\xtradev.cm
copy %cmsrc%\spice2poly64.cm %dst%\lib\ngspice\spice2poly.cm

View File

@ -17,6 +17,7 @@ mkdir %dst%\share\ngspice\scripts
copy "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.OPENMP\vcomp140.dll" %dst%\bin\
copy %cmsrc%\analog.cm %dst%\lib\ngspice\analog.cm
copy %cmsrc%\digital.cm %dst%\lib\ngspice\digital.cm
copy %cmsrc%\table.cm %dst%\lib\ngspice\table.cm
copy %cmsrc%\xtraevt.cm %dst%\lib\ngspice\xtraevt.cm
copy %cmsrc%\xtradev.cm %dst%\lib\ngspice\xtradev.cm
copy %cmsrc%\spice2poly.cm %dst%\lib\ngspice\spice2poly.cm
@ -45,6 +46,7 @@ mkdir %dst%\share\ngspice\scripts
copy "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.OPENMP\vcomp140.dll" %dst%\bin\
copy %cmsrc%\analog64.cm %dst%\lib\ngspice\analog.cm
copy %cmsrc%\digital64.cm %dst%\lib\ngspice\digital.cm
copy %cmsrc%\table64.cm %dst%\lib\ngspice\table.cm
copy %cmsrc%\xtraevt64.cm %dst%\lib\ngspice\xtraevt.cm
copy %cmsrc%\xtradev64.cm %dst%\lib\ngspice\xtradev.cm
copy %cmsrc%\spice2poly64.cm %dst%\lib\ngspice\spice2poly.cm

View File

@ -27,6 +27,7 @@ if $__flag = 0
codemodel C:/Spice/lib/ngspice/digital.cm
codemodel C:/Spice/lib/ngspice/xtradev.cm
codemodel C:/Spice/lib/ngspice/xtraevt.cm
codemodel C:/Spice/lib/ngspice/table.cm
end
unset __flag

View File

@ -27,6 +27,7 @@ if $__flag = 0
codemodel C:/Spice64/lib/ngspice/digital.cm
codemodel C:/Spice64/lib/ngspice/xtradev.cm
codemodel C:/Spice64/lib/ngspice/xtraevt.cm
codemodel C:/Spice64/lib/ngspice/table.cm
end
unset __flag

View File

@ -27,6 +27,7 @@ if $__flag = 0
codemodel C:/Spiced/lib/ngspice/digital.cm
codemodel C:/Spiced/lib/ngspice/xtradev.cm
codemodel C:/Spiced/lib/ngspice/xtraevt.cm
codemodel C:/Spiced/lib/ngspice/table.cm
end
unset __flag

View File

@ -27,6 +27,7 @@ if $__flag = 0
codemodel C:/Spice64d/lib/ngspice/digital.cm
codemodel C:/Spice64d/lib/ngspice/xtradev.cm
codemodel C:/Spice64d/lib/ngspice/xtraevt.cm
codemodel C:/Spice64d/lib/ngspice/table.cm
end
unset __flag

View File

@ -31,6 +31,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spice2poly", "xspice\spice2
{7C865696-FA10-43AE-A20B-22AE72A165E2} = {7C865696-FA10-43AE-A20B-22AE72A165E2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "table", "xspice\table.vcxproj", "{7A6473F5-AFED-4910-88D2-6204DA829832}"
ProjectSection(ProjectDependencies) = postProject
{7C865696-FA10-43AE-A20B-22AE72A165E2} = {7C865696-FA10-43AE-A20B-22AE72A165E2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xtradev", "xspice\xtradev.vcxproj", "{4BB60215-9A09-4192-9DB6-1A0CA823AFCA}"
ProjectSection(ProjectDependencies) = postProject
{7C865696-FA10-43AE-A20B-22AE72A165E2} = {7C865696-FA10-43AE-A20B-22AE72A165E2}

View File

@ -31,6 +31,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spice2poly", "xspice\spice2
{7C865696-FA10-43AE-A20B-22AE72A165E2} = {7C865696-FA10-43AE-A20B-22AE72A165E2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "table", "xspice\table.vcxproj", "{7A6473F5-AFED-4910-88D2-6204DA829832}"
ProjectSection(ProjectDependencies) = postProject
{7C865696-FA10-43AE-A20B-22AE72A165E2} = {7C865696-FA10-43AE-A20B-22AE72A165E2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xtradev", "xspice\xtradev.vcxproj", "{4BB60215-9A09-4192-9DB6-1A0CA823AFCA}"
ProjectSection(ProjectDependencies) = postProject
{7C865696-FA10-43AE-A20B-22AE72A165E2} = {7C865696-FA10-43AE-A20B-22AE72A165E2}

View File

@ -0,0 +1,225 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>table</ProjectName>
<ProjectGuid>{7A6473F5-AFED-4910-88D2-6204DA829832}</ProjectGuid>
<RootNamespace>icmanalog</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<TargetExt>.cm</TargetExt>
<OutDir>$(SolutionDir)codemodels\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)xspice\intermediate\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<GenerateManifest>true</GenerateManifest>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TargetName>$(ProjectName)64</TargetName>
<GenerateManifest>true</GenerateManifest>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<TargetName>$(ProjectName)64</TargetName>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup>
<PreBuildEvent>
<Message>generate cfunc.c and ifspec.c files</Message>
<Command>call .\aux-cfunc.bat $(ProjectName)</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>icm\$(ProjectName);..\src\include;..\..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;CIDER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AssemblyDebug>
</AssemblyDebug>
<SubSystem>Windows</SubSystem>
<NoEntryPoint>false</NoEntryPoint>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>icm\$(ProjectName);..\src\include;..\..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<NoEntryPoint>false</NoEntryPoint>
<ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>icm\$(ProjectName);..\src\include;..\..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;CIDER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AssemblyDebug>
</AssemblyDebug>
<SubSystem>Windows</SubSystem>
<NoEntryPoint>false</NoEntryPoint>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>icm\$(ProjectName);..\src\include;..\..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<NoEntryPoint>false</NoEntryPoint>
<ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="icm\table\table2D\table2D-cfunc.c">
<AdditionalIncludeDirectories>..\..\src\xspice\icm\$(ProjectName);..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="icm\table\table2D\table2D-ifspec.c" />
<ClCompile Include="icm\table\table3D\table3D-cfunc.c">
<AdditionalIncludeDirectories>..\..\src\xspice\icm\$(ProjectName);..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="icm\table\table3D\table3D-ifspec.c" />
<ClCompile Include="..\..\src\xspice\icm\dlmain.c" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\xspice\icm\table\table2D\cfunc.mod" />
<None Include="..\..\src\xspice\icm\table\table2D\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\table\table3D\cfunc.mod" />
<None Include="..\..\src\xspice\icm\table\table3D\ifspec.ifs" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xtraevt", "xtraevt.vcxproj"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xtradev", "xtradev.vcxproj", "{4BB60215-9A09-4192-9DB6-1A0CA823AFCA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "table", "table.vcxproj", "{7A6473F5-AFED-4910-88D2-6204DA829832}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spice2poly", "spice2poly.vcxproj", "{D701EA0E-B8B0-41D6-A90E-A0D8233F15FB}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "digital", "digital.vcxproj", "{9ABEC5F2-F6C6-41DE-88AB-02460A07F46E}"