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:
parent
2c3c632349
commit
96a1b528fd
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue