diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 4b8e9a87c..1725503e3 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -52,7 +52,7 @@ Author: 1985 Wayne A. Christopher /* gtri - end - 12/12/90 */ #endif -/* #define INTEGRATE_UDEVICES */ +#define INTEGRATE_UDEVICES #ifdef INTEGRATE_UDEVICES #include "ngspice/udevices.h" #endif @@ -8287,21 +8287,43 @@ static void rem_double_braces(struct card* newcard) } #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) { struct card *card, *returncard = NULL, *subcktcard = NULL; + struct card *newcard = NULL, *last_newcard = NULL; int level = 0; int models_ok = 0, models_not_ok = 0; int udev_ok = 0, udev_not_ok = 0; BOOL create_called = FALSE, repeat_pass = FALSE; - BOOL skip_next = FALSE; + BOOL skip_next = FALSE, verbose = FALSE; + char *tmp = NULL, *pos; card = startcard; while (card) { char *cut_line = card->line; skip_next = FALSE; - printf("line: %s\n", cut_line); + if (verbose) printf("line: %s\n", cut_line); if (ciprefix(".subckt", cut_line)) { models_ok = models_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"); break; } + tmp = TMALLOC(char, strlen(cut_line) + 1); + (void) memcpy(tmp, cut_line, strlen(cut_line) + 1); subcktcard = card; - printf("** subckt: %s\n", cut_line); + if (verbose) printf("** subckt: %s\n", cut_line); if (!repeat_pass) { if (create_called) { - cleanup_model_xlator(); + cleanup_udevice(); } - create_model_xlator(); + initialize_udevice(); create_called = TRUE; - printf("Doing first pass\n"); + if (verbose) printf("Doing first pass\n"); } 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)) { level--; - printf("** ends: %s\n", cut_line); + if (verbose) printf("** ends: %s\n", cut_line); 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 { - 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); if (models_not_ok > 0 || udev_not_ok > 0) { repeat_pass = FALSE; - cleanup_model_xlator(); + cleanup_udevice(); create_called = FALSE; } else if (udev_ok > 0) { - printf("Repeat subckt\n"); + if (verbose) printf("Repeat subckt\n"); repeat_pass = TRUE; card = subcktcard; skip_next = TRUE; } else { repeat_pass = FALSE; - cleanup_model_xlator(); + cleanup_udevice(); create_called = FALSE; } subcktcard = NULL; } else if (ciprefix(".model", cut_line)) { 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)) { - printf("Unable to convert model\n"); + if (verbose) printf("Unable to convert model\n"); models_not_ok++; } else { models_ok++; @@ -8360,30 +8402,32 @@ static struct card *u_instances(struct card *startcard) } } else if (ciprefix("u", cut_line)) { if (subcktcard) { - printf("** instance: %s\n", cut_line); + if (verbose) printf("** instance: %s\n", cut_line); if (repeat_pass) { if (!u_process_instance(cut_line)) { /* Bail out */ - printf("Unable to convert instance\n"); + if (verbose) printf("Unable to convert instance\n"); break; } } else { if (u_check_instance(cut_line)) { - printf("Instance can be converted\n"); + if (verbose) printf("Instance can be converted\n"); udev_ok++; } else { - printf("Instance can NOT be converted\n"); + if (verbose) printf("Instance can NOT be converted\n"); udev_not_ok++; } } } + } else { + udev_not_ok++; } if (!skip_next) { card = card->nextcard; } } if (create_called) { - cleanup_model_xlator(); + cleanup_udevice(); } return returncard; } @@ -8435,10 +8479,13 @@ static struct card *pspice_compat(struct card *oldcard) } #ifdef INTEGRATE_UDEVICES + //list_the_cards(oldcard, "After AKO"); +/* Here { struct card *ucard; ucard = u_instances(oldcard); } +*/ #endif /* 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->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 */ /* FIXME: This should not be necessary if we had a better sense of hierarchy during the evaluation of TEMPER */ diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index 3176ff5cb..d1db45da0 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -17,10 +17,13 @@ hazard detection. 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, 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 u_process_instance_line() (or similar). This calls translate_...() @@ -29,7 +32,7 @@ gen_..._instance(). Creating new cards to replace the U* and .model cards needs modifying where the output goes from processing an instance. 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. */ @@ -44,13 +47,13 @@ #include "ngspice/bool.h" #include "ngspice/stringskip.h" #include "ngspice/stringutil.h" +#include "ngspice/inpdefs.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 */ #define D_AND 0 @@ -160,6 +163,10 @@ typedef struct s_xlator { Xlatep iter; } Xlator; +#ifdef TRACE +static void interpret_xlator(Xlatorp xp, BOOL brief); +#endif + /* For timing model extraction */ #define EST_UNK -1 #define EST_MIN 0 @@ -324,25 +331,21 @@ static void delete_xlate(Xlatep p) static Xlatep create_xlate(char *translated, char *delays, char *utype, char *xspice, char *tmodel, char *mname) { + /* Any unused parameter is called with an empty string "" */ Xlatep xlp; xlp = TMALLOC(Xlate, 1); xlp->next = NULL; xlp->translated = TMALLOC(char, strlen(translated) + 1); strcpy(xlp->translated, translated); - xlp->delays = TMALLOC(char, strlen(delays) + 1); strcpy(xlp->delays, delays); - xlp->utype = TMALLOC(char, strlen(utype) + 1); strcpy(xlp->utype, utype); - xlp->xspice = TMALLOC(char, strlen(xspice) + 1); strcpy(xlp->xspice, xspice); - xlp->tmodel = TMALLOC(char, strlen(tmodel) + 1); strcpy(xlp->tmodel, tmodel); - xlp->mname = TMALLOC(char, strlen(mname) + 1); strcpy(xlp->mname, mname); return xlp; @@ -448,6 +451,19 @@ static Xlatep next_xlator(Xlatorp xp) 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 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 model_xlatorp = 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; + create_translated_xlator(); model_xlatorp = create_xlator(); default_models = create_xlator(); /* .model d0_gate ugate () */ @@ -500,8 +564,9 @@ void create_model_xlator(void) (void) add_xlator(default_models, xdata); } -void cleanup_model_xlator(void) +void cleanup_udevice(void) { + cleanup_translated_xlator(); delete_xlator(model_xlatorp); model_xlatorp = NULL; delete_xlator(default_models); @@ -2684,6 +2749,7 @@ BOOL u_process_instance(char *nline) retval = FALSE; } if (xp) { + append_xlator(translated_p, xp); #ifdef TRACE interpret_xlator(xp, TRUE); #endif diff --git a/src/include/ngspice/udevices.h b/src/include/ngspice/udevices.h index 116ef9fe9..36ce687fd 100644 --- a/src/include/ngspice/udevices.h +++ b/src/include/ngspice/udevices.h @@ -4,7 +4,8 @@ BOOL u_process_instance(char *line); BOOL u_process_model_line(char *line); BOOL u_check_instance(char *line); -void create_model_xlator(void); -void cleanup_model_xlator(void); +void initialize_udevice(void); +struct card *replacement_udevice_cards(void); +void cleanup_udevice(void); #endif