Replace Pspice U* and .model cards with their Xspice equivalent statements. There are still memory leaks which will be plugged next. The .subckts have only digital ports, which will need to addressed for mixed A/D designs.

This commit is contained in:
Brian Taylor 2022-05-05 20:50:36 -07:00 committed by Holger Vogt
parent 2c3c632349
commit 96a1b528fd
3 changed files with 165 additions and 39 deletions

View File

@ -52,7 +52,7 @@ Author: 1985 Wayne A. Christopher
/* gtri - end - 12/12/90 */ /* gtri - end - 12/12/90 */
#endif #endif
/* #define INTEGRATE_UDEVICES */ #define INTEGRATE_UDEVICES
#ifdef INTEGRATE_UDEVICES #ifdef INTEGRATE_UDEVICES
#include "ngspice/udevices.h" #include "ngspice/udevices.h"
#endif #endif
@ -8287,21 +8287,43 @@ static void rem_double_braces(struct card* newcard)
} }
#ifdef INTEGRATE_UDEVICES #ifdef INTEGRATE_UDEVICES
static void list_the_cards(struct card *startcard, char *prefix)
{
struct card *card;
if (!startcard) { return; }
for (card = startcard; card; card = card->nextcard) {
char* cut_line = card->line;
printf("%s %s\n", prefix, cut_line);
}
}
static struct card *the_last_card(struct card *startcard)
{
struct card *card, *lastcard = NULL;
if (!startcard) { return NULL; }
for (card = startcard; card; card = card->nextcard) {
lastcard = card;
}
return lastcard;
}
static struct card *u_instances(struct card *startcard) static struct card *u_instances(struct card *startcard)
{ {
struct card *card, *returncard = NULL, *subcktcard = NULL; struct card *card, *returncard = NULL, *subcktcard = NULL;
struct card *newcard = NULL, *last_newcard = NULL;
int level = 0; int level = 0;
int models_ok = 0, models_not_ok = 0; int models_ok = 0, models_not_ok = 0;
int udev_ok = 0, udev_not_ok = 0; int udev_ok = 0, udev_not_ok = 0;
BOOL create_called = FALSE, repeat_pass = FALSE; BOOL create_called = FALSE, repeat_pass = FALSE;
BOOL skip_next = FALSE; BOOL skip_next = FALSE, verbose = FALSE;
char *tmp = NULL, *pos;
card = startcard; card = startcard;
while (card) { while (card) {
char *cut_line = card->line; char *cut_line = card->line;
skip_next = FALSE; skip_next = FALSE;
printf("line: %s\n", cut_line); if (verbose) printf("line: %s\n", cut_line);
if (ciprefix(".subckt", cut_line)) { if (ciprefix(".subckt", cut_line)) {
models_ok = models_not_ok = 0; models_ok = models_not_ok = 0;
udev_ok = udev_not_ok = 0; udev_ok = udev_not_ok = 0;
@ -8311,48 +8333,68 @@ static struct card *u_instances(struct card *startcard)
printf("Too many nesting levels\n"); printf("Too many nesting levels\n");
break; break;
} }
tmp = TMALLOC(char, strlen(cut_line) + 1);
(void) memcpy(tmp, cut_line, strlen(cut_line) + 1);
subcktcard = card; subcktcard = card;
printf("** subckt: %s\n", cut_line); if (verbose) printf("** subckt: %s\n", cut_line);
if (!repeat_pass) { if (!repeat_pass) {
if (create_called) { if (create_called) {
cleanup_model_xlator(); cleanup_udevice();
} }
create_model_xlator(); initialize_udevice();
create_called = TRUE; create_called = TRUE;
printf("Doing first pass\n"); if (verbose) printf("Doing first pass\n");
} else { } else {
printf("Doing second pass\n"); pos = strstr(tmp, "optional");
if (pos) {
*pos = '\0';
}
//printf(" %s\n", tmp);
if (verbose) printf("Doing second pass\n");
} }
//tfree(tmp);
} else if (ciprefix(".ends", cut_line)) { } else if (ciprefix(".ends", cut_line)) {
level--; level--;
printf("** ends: %s\n", cut_line); if (verbose) printf("** ends: %s\n", cut_line);
if (repeat_pass) { if (repeat_pass) {
printf("Second pass "); newcard = replacement_udevice_cards();
if (newcard) {
subcktcard->nextcard = newcard;
tfree(subcktcard->line);
subcktcard->line = tmp;
//list_the_cards(newcard, "Replacement:");
last_newcard = the_last_card(newcard);
if (last_newcard) {
last_newcard->nextcard = card; // the .ends card
}
}
if (verbose) printf("Second pass ");
//printf(" %s\n", cut_line);
} else { } else {
printf("First pass "); if (verbose) printf("First pass ");
} }
printf("udev_ok=%d udev_not_ok=%d models_ok=%d models_not_ok=%d\n", if (verbose) printf("udev_ok=%d udev_not_ok=%d models_ok=%d models_not_ok=%d\n",
udev_ok, udev_not_ok, models_ok, models_not_ok); udev_ok, udev_not_ok, models_ok, models_not_ok);
if (models_not_ok > 0 || udev_not_ok > 0) { if (models_not_ok > 0 || udev_not_ok > 0) {
repeat_pass = FALSE; repeat_pass = FALSE;
cleanup_model_xlator(); cleanup_udevice();
create_called = FALSE; create_called = FALSE;
} else if (udev_ok > 0) { } else if (udev_ok > 0) {
printf("Repeat subckt\n"); if (verbose) printf("Repeat subckt\n");
repeat_pass = TRUE; repeat_pass = TRUE;
card = subcktcard; card = subcktcard;
skip_next = TRUE; skip_next = TRUE;
} else { } else {
repeat_pass = FALSE; repeat_pass = FALSE;
cleanup_model_xlator(); cleanup_udevice();
create_called = FALSE; create_called = FALSE;
} }
subcktcard = NULL; subcktcard = NULL;
} else if (ciprefix(".model", cut_line)) { } else if (ciprefix(".model", cut_line)) {
if (subcktcard && !repeat_pass) { if (subcktcard && !repeat_pass) {
printf("** model: %s\n", cut_line); if (verbose) printf("** model: %s\n", cut_line);
if (!u_process_model_line(cut_line)) { if (!u_process_model_line(cut_line)) {
printf("Unable to convert model\n"); if (verbose) printf("Unable to convert model\n");
models_not_ok++; models_not_ok++;
} else { } else {
models_ok++; models_ok++;
@ -8360,30 +8402,32 @@ static struct card *u_instances(struct card *startcard)
} }
} else if (ciprefix("u", cut_line)) { } else if (ciprefix("u", cut_line)) {
if (subcktcard) { if (subcktcard) {
printf("** instance: %s\n", cut_line); if (verbose) printf("** instance: %s\n", cut_line);
if (repeat_pass) { if (repeat_pass) {
if (!u_process_instance(cut_line)) { if (!u_process_instance(cut_line)) {
/* Bail out */ /* Bail out */
printf("Unable to convert instance\n"); if (verbose) printf("Unable to convert instance\n");
break; break;
} }
} else { } else {
if (u_check_instance(cut_line)) { if (u_check_instance(cut_line)) {
printf("Instance can be converted\n"); if (verbose) printf("Instance can be converted\n");
udev_ok++; udev_ok++;
} else { } else {
printf("Instance can NOT be converted\n"); if (verbose) printf("Instance can NOT be converted\n");
udev_not_ok++; udev_not_ok++;
} }
} }
} }
} else {
udev_not_ok++;
} }
if (!skip_next) { if (!skip_next) {
card = card->nextcard; card = card->nextcard;
} }
} }
if (create_called) { if (create_called) {
cleanup_model_xlator(); cleanup_udevice();
} }
return returncard; return returncard;
} }
@ -8435,10 +8479,13 @@ static struct card *pspice_compat(struct card *oldcard)
} }
#ifdef INTEGRATE_UDEVICES #ifdef INTEGRATE_UDEVICES
//list_the_cards(oldcard, "After AKO");
/* Here
{ {
struct card *ucard; struct card *ucard;
ucard = u_instances(oldcard); ucard = u_instances(oldcard);
} }
*/
#endif #endif
/* Process .distribution cards. */ /* Process .distribution cards. */
@ -8474,6 +8521,18 @@ static struct card *pspice_compat(struct card *oldcard)
nextcard = insert_new_line(nextcard, new_str, 9, 0); nextcard = insert_new_line(nextcard, new_str, 9, 0);
nextcard->nextcard = oldcard; nextcard->nextcard = oldcard;
#ifdef INTEGRATE_UDEVICES
/* or here? */
{
struct card *ucard;
//ucard = u_instances(oldcard);
//ucard = u_instances(nextcard);
ucard = u_instances(newcard);
list_the_cards(oldcard, "After udevices");
}
#endif
/* add predefined parameters TEMP, VT after each subckt call */ /* add predefined parameters TEMP, VT after each subckt call */
/* FIXME: This should not be necessary if we had a better sense of /* FIXME: This should not be necessary if we had a better sense of
hierarchy during the evaluation of TEMPER */ hierarchy during the evaluation of TEMPER */

View File

@ -17,10 +17,13 @@
hazard detection. hazard detection.
Only the common logic gates, flip-flops, and latches are suported. Only the common logic gates, flip-flops, and latches are suported.
First pass through a subcircuit. Call create_model_xlator() and read the First pass through a subcircuit. Call initialize_udevice() and read the
.model cards by calling u_process_model_line() (or similar) for each card, .model cards by calling u_process_model_line() (or similar) for each card,
The delays for the different types (ugate, utgate, ueff, ugff) are stored The delays for the different types (ugate, utgate, ueff, ugff) are stored
by get_delays_...() and add_delays_to_model_xlator(). by get_delays_...() and add_delays_to_model_xlator(). Also, during the
first pass, check that each U* instance can be translated to Xspice.
If there are any .model or U* instance cards that cannot be processed
in the .subckt, then there is no second pass and the .subckt is skipped.
Second pass through a subcircuit. To translate each U* instance call Second pass through a subcircuit. To translate each U* instance call
u_process_instance_line() (or similar). This calls translate_...() u_process_instance_line() (or similar). This calls translate_...()
@ -29,7 +32,7 @@
gen_..._instance(). Creating new cards to replace the U* and .model gen_..._instance(). Creating new cards to replace the U* and .model
cards needs modifying where the output goes from processing an instance. cards needs modifying where the output goes from processing an instance.
This will be added either to this file or to frontend/inpcom.c. This will be added either to this file or to frontend/inpcom.c.
Finally, call cleanup_model_xlator() before repeating the sequence for Finally, call cleanup_udevice() before repeating the sequence for
another subcircuit. another subcircuit.
*/ */
@ -44,13 +47,13 @@
#include "ngspice/bool.h" #include "ngspice/bool.h"
#include "ngspice/stringskip.h" #include "ngspice/stringskip.h"
#include "ngspice/stringutil.h" #include "ngspice/stringutil.h"
#include "ngspice/inpdefs.h"
#include "ngspice/udevices.h" #include "ngspice/udevices.h"
/*
TODO check for name collisions when creating new names
TODO add support for oa and oai gates, srff, pullup/down
*/
#define TRACE extern struct card* insert_new_line(
struct card* card, char* line, int linenum, int linenum_orig);
/* #define TRACE */
/* device types */ /* device types */
#define D_AND 0 #define D_AND 0
@ -160,6 +163,10 @@ typedef struct s_xlator {
Xlatep iter; Xlatep iter;
} Xlator; } Xlator;
#ifdef TRACE
static void interpret_xlator(Xlatorp xp, BOOL brief);
#endif
/* For timing model extraction */ /* For timing model extraction */
#define EST_UNK -1 #define EST_UNK -1
#define EST_MIN 0 #define EST_MIN 0
@ -324,25 +331,21 @@ static void delete_xlate(Xlatep p)
static Xlatep create_xlate(char *translated, char *delays, char *utype, static Xlatep create_xlate(char *translated, char *delays, char *utype,
char *xspice, char *tmodel, char *mname) char *xspice, char *tmodel, char *mname)
{ {
/* Any unused parameter is called with an empty string "" */
Xlatep xlp; Xlatep xlp;
xlp = TMALLOC(Xlate, 1); xlp = TMALLOC(Xlate, 1);
xlp->next = NULL; xlp->next = NULL;
xlp->translated = TMALLOC(char, strlen(translated) + 1); xlp->translated = TMALLOC(char, strlen(translated) + 1);
strcpy(xlp->translated, translated); strcpy(xlp->translated, translated);
xlp->delays = TMALLOC(char, strlen(delays) + 1); xlp->delays = TMALLOC(char, strlen(delays) + 1);
strcpy(xlp->delays, delays); strcpy(xlp->delays, delays);
xlp->utype = TMALLOC(char, strlen(utype) + 1); xlp->utype = TMALLOC(char, strlen(utype) + 1);
strcpy(xlp->utype, utype); strcpy(xlp->utype, utype);
xlp->xspice = TMALLOC(char, strlen(xspice) + 1); xlp->xspice = TMALLOC(char, strlen(xspice) + 1);
strcpy(xlp->xspice, xspice); strcpy(xlp->xspice, xspice);
xlp->tmodel = TMALLOC(char, strlen(tmodel) + 1); xlp->tmodel = TMALLOC(char, strlen(tmodel) + 1);
strcpy(xlp->tmodel, tmodel); strcpy(xlp->tmodel, tmodel);
xlp->mname = TMALLOC(char, strlen(mname) + 1); xlp->mname = TMALLOC(char, strlen(mname) + 1);
strcpy(xlp->mname, mname); strcpy(xlp->mname, mname);
return xlp; return xlp;
@ -448,6 +451,19 @@ static Xlatep next_xlator(Xlatorp xp)
return ret; return ret;
} }
static Xlatorp append_xlator(Xlatorp dest, Xlatorp src)
{
Xlatep x1, copy;
if (!dest || !src) { return NULL; }
for (x1 = first_xlator(src); x1; x1 = next_xlator(src)) {
copy = create_xlate(x1->translated, x1->delays, x1->utype,
x1->xspice, x1->tmodel, x1->mname);
dest = add_xlator(dest, copy);
}
return dest;
}
#ifdef TRACE #ifdef TRACE
static void interpret_xlator(Xlatorp xp, BOOL brief) static void interpret_xlator(Xlatorp xp, BOOL brief)
{ {
@ -479,11 +495,59 @@ static void interpret_xlator(Xlatorp xp, BOOL brief)
/* static Xlatorp for collecting timing model delays */ /* static Xlatorp for collecting timing model delays */
static Xlatorp model_xlatorp = NULL; static Xlatorp model_xlatorp = NULL;
static Xlatorp default_models = NULL; static Xlatorp default_models = NULL;
static Xlatorp translated_p = NULL;
void create_model_xlator(void) static void create_translated_xlator(void)
{
translated_p = create_xlator();
}
static void cleanup_translated_xlator(void)
{
#ifdef TRACE
printf("\nStart cleanup\n");
interpret_xlator(translated_p, TRUE);
printf("End cleanup\n");
#endif
delete_xlator(translated_p);
translated_p = NULL;
}
struct card *replacement_udevice_cards(void)
{
struct card *newcard = NULL, *nextcard = NULL;
char *new_str = NULL;
Xlatep x;
int count = 0;
if (!translated_p) { return NULL; }
for (x = first_xlator(translated_p); x; x = next_xlator(translated_p)) {
new_str = copy(x->translated);
if (count == 0) {
count++;
newcard = insert_new_line(NULL, new_str, 0, 0);
} else if (count == 1) {
count++;
nextcard = insert_new_line(newcard, new_str, 0, 0);
} else {
count++;
nextcard = insert_new_line(nextcard, new_str, 0, 0);
}
}
/*
for (card = newcard; card; card = card->nextcard) {
char* cut_line = card->line;
printf("NEW CARD: %s\n", cut_line);
}
*/
return newcard;
}
void initialize_udevice(void)
{ {
Xlatep xdata; Xlatep xdata;
create_translated_xlator();
model_xlatorp = create_xlator(); model_xlatorp = create_xlator();
default_models = create_xlator(); default_models = create_xlator();
/* .model d0_gate ugate () */ /* .model d0_gate ugate () */
@ -500,8 +564,9 @@ void create_model_xlator(void)
(void) add_xlator(default_models, xdata); (void) add_xlator(default_models, xdata);
} }
void cleanup_model_xlator(void) void cleanup_udevice(void)
{ {
cleanup_translated_xlator();
delete_xlator(model_xlatorp); delete_xlator(model_xlatorp);
model_xlatorp = NULL; model_xlatorp = NULL;
delete_xlator(default_models); delete_xlator(default_models);
@ -2684,6 +2749,7 @@ BOOL u_process_instance(char *nline)
retval = FALSE; retval = FALSE;
} }
if (xp) { if (xp) {
append_xlator(translated_p, xp);
#ifdef TRACE #ifdef TRACE
interpret_xlator(xp, TRUE); interpret_xlator(xp, TRUE);
#endif #endif

View File

@ -4,7 +4,8 @@
BOOL u_process_instance(char *line); BOOL u_process_instance(char *line);
BOOL u_process_model_line(char *line); BOOL u_process_model_line(char *line);
BOOL u_check_instance(char *line); BOOL u_check_instance(char *line);
void create_model_xlator(void); void initialize_udevice(void);
void cleanup_model_xlator(void); struct card *replacement_udevice_cards(void);
void cleanup_udevice(void);
#endif #endif