Fix a memory leak. Cleanup the code a bit. All-digital Pspice subckts with U* devices for most used gates/ff can be handled. More extensive test cases are necessary. Also, interfacing subckts with analog ports is not implemented.

This commit is contained in:
Brian Taylor 2022-05-06 14:34:33 -07:00 committed by Holger Vogt
parent 701ed7beb0
commit 63cec9668c
2 changed files with 38 additions and 76 deletions

View File

@ -8287,6 +8287,7 @@ static void rem_double_braces(struct card* newcard)
}
#ifdef INTEGRATE_UDEVICES
/*
static void list_the_cards(struct card *startcard, char *prefix)
{
struct card *card;
@ -8296,6 +8297,7 @@ static void list_the_cards(struct card *startcard, char *prefix)
printf("%s %s\n", prefix, cut_line);
}
}
*/
static struct card *the_last_card(struct card *startcard)
{
@ -8305,6 +8307,19 @@ static struct card *the_last_card(struct card *startcard)
lastcard = card;
}
return lastcard;
}
static void remove_old_cards(struct card *first, struct card *stop)
{
struct card *x, *next = NULL;
if (!first || !stop || (first == stop)) { return; }
for (x = first; (x && (x != stop)); x = next) {
//printf("Remove %s\n", x->line);
if (x->line) { tfree(x->line); }
if (x->error) { tfree(x->error); }
next = x->nextcard;
tfree(x);
}
}
static struct card *u_instances(struct card *startcard)
@ -8315,15 +8330,14 @@ static struct card *u_instances(struct card *startcard)
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, verbose = FALSE;
char *tmp = NULL, *pos;
BOOL skip_next = FALSE;
char *tmp = NULL, *pos, *new_str = NULL;
card = startcard;
while (card) {
char *cut_line = card->line;
skip_next = FALSE;
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;
@ -8333,54 +8347,44 @@ 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;
if (verbose) printf("** subckt: %s\n", cut_line);
if (!repeat_pass) {
if (create_called) {
cleanup_udevice();
}
initialize_udevice();
create_called = TRUE;
if (verbose) printf("Doing first pass\n");
} else {
pos = strstr(tmp, "optional");
if (pos) {
*pos = '\0';
}
//printf(" %s\n", tmp);
if (verbose) printf("Doing second pass\n");
tmp = TMALLOC(char, strlen(cut_line) + 1);
(void) memcpy(tmp, cut_line, strlen(cut_line) + 1);
pos = strstr(tmp, "optional");
if (pos) {
*pos = '\0';
}
new_str = copy(tmp);
tfree(tmp);
}
//tfree(tmp);
} else if (ciprefix(".ends", cut_line)) {
level--;
if (verbose) printf("** ends: %s\n", cut_line);
if (repeat_pass) {
newcard = replacement_udevice_cards();
if (newcard) {
remove_old_cards(subcktcard->nextcard, card);
subcktcard->nextcard = newcard;
tfree(subcktcard->line);
subcktcard->line = tmp;
subcktcard->line = new_str;
//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 {
if (verbose) printf("First pass ");
}
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_udevice();
create_called = FALSE;
} else if (udev_ok > 0) {
if (verbose) printf("Repeat subckt\n");
repeat_pass = TRUE;
card = subcktcard;
skip_next = TRUE;
@ -8392,9 +8396,7 @@ static struct card *u_instances(struct card *startcard)
subcktcard = NULL;
} else if (ciprefix(".model", cut_line)) {
if (subcktcard && !repeat_pass) {
if (verbose) printf("** model: %s\n", cut_line);
if (!u_process_model_line(cut_line)) {
if (verbose) printf("Unable to convert model\n");
models_not_ok++;
} else {
models_ok++;
@ -8402,19 +8404,15 @@ static struct card *u_instances(struct card *startcard)
}
} else if (ciprefix("u", cut_line)) {
if (subcktcard) {
if (verbose) printf("** instance: %s\n", cut_line);
if (repeat_pass) {
if (!u_process_instance(cut_line)) {
/* Bail out */
if (verbose) printf("Unable to convert instance\n");
break;
}
} else {
if (u_check_instance(cut_line)) {
if (verbose) printf("Instance can be converted\n");
udev_ok++;
} else {
if (verbose) printf("Instance can NOT be converted\n");
udev_not_ok++;
}
}
@ -8478,16 +8476,6 @@ static struct card *pspice_compat(struct card *oldcard)
controlled_exit(1);
}
#ifdef INTEGRATE_UDEVICES
//list_the_cards(oldcard, "After AKO");
/* Here
{
struct card *ucard;
ucard = u_instances(oldcard);
}
*/
#endif
/* Process .distribution cards. */
do_distribution(oldcard);
@ -8522,13 +8510,10 @@ static struct card *pspice_compat(struct card *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");
//list_the_cards(oldcard, "After udevices");
}
#endif

View File

@ -30,10 +30,11 @@
functions for gates, tristate, flip-flops and latches. translate_...()
calls add_..._inout_timing_model() to parse the U* card, and then calls
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_udevice() before repeating the sequence for
another subcircuit.
cards is done by calling replacement_udevice_cards(), which returns a
list of new cards. The list of cards is then to be inserted after the
.subckt card and before the .ends card. This occurs in the function
u_instances() in frontend/inpcom.c. Finally, call cleanup_udevice()
before repeating the sequence for another subcircuit.
*/
#include <stdio.h>
@ -2126,6 +2127,7 @@ static char *get_delays_ugff(char *rem, char *d_name)
return delays;
}
/*
static void print_delays(char *delays)
{
if (delays) {
@ -2135,26 +2137,22 @@ static void print_delays(char *delays)
}
return;
}
*/
static BOOL u_process_model(char *nline, char *original,
char *newname, char *xspice)
{
char *tok, *remainder, *delays = NULL, *utype, *tmodel;
BOOL retval = TRUE, verbose = FALSE;
#ifdef TRACE
//verbose = TRUE;
#endif
BOOL retval = TRUE;
/* .model */
tok = strtok(nline, " \t");
/* model name */
tok = strtok(NULL, " \t");
if (verbose) printf("\nmodel_name -> %s\n", tok);
tmodel = TMALLOC(char, strlen(tok) + 1);
memcpy(tmodel, tok, strlen(tok) + 1);
/* model utype */
tok = strtok(NULL, " \t(");
if (verbose) printf("model_utype -> %s\n", tok);
utype = TMALLOC(char, strlen(tok) + 1);
memcpy(utype, tok, strlen(tok) + 1);
@ -2165,30 +2163,25 @@ static BOOL u_process_model(char *nline, char *original,
delays = get_delays_ugate(remainder, xspice);
add_delays_to_model_xlator((delays ? delays : ""),
utype, "", tmodel);
if (verbose) print_delays(delays);
if (delays) { tfree(delays); }
} else if (strcmp(utype, "utgate") == 0) {
delays = get_delays_utgate(remainder, xspice);
add_delays_to_model_xlator((delays ? delays : ""),
utype, "", tmodel);
if (verbose) print_delays(delays);
if (delays) { tfree(delays); }
} else if (strcmp(utype, "ueff") == 0) {
delays = get_delays_ueff(remainder, xspice);
add_delays_to_model_xlator((delays ? delays : ""),
utype, "", tmodel);
if (verbose) print_delays(delays);
if (delays) { tfree(delays); }
} else if (strcmp(utype, "ugff") == 0) {
delays = get_delays_ugff(remainder, "d_dlatch");
add_delays_to_model_xlator((delays ? delays : ""),
utype, "d_dlatch", tmodel);
if (verbose) print_delays(delays);
if (delays) { tfree(delays); }
delays = get_delays_ugff(remainder, "d_srlatch");
add_delays_to_model_xlator((delays ? delays : ""),
utype, "d_srlatch", tmodel);
if (verbose) print_delays(delays);
if (delays) { tfree(delays); }
} else {
retval = FALSE;
@ -2439,7 +2432,7 @@ static struct gate_instance *add_array_inout_timing_model(
struct instance_hdr *hdr, char *start)
{
char *tok, *copyline, *itype = hdr->instance_type;
BOOL first = TRUE, tristate = FALSE, verbose = FALSE;
BOOL first = TRUE, tristate = FALSE;
int i, j, k, n1 =hdr->num1, n2 = hdr->num2, inwidth, numgates;
struct gate_instance *gip = NULL;
char **inarr = NULL, **outarr = NULL, *name;
@ -2475,10 +2468,6 @@ static struct gate_instance *add_array_inout_timing_model(
gip->num_outs = numgates;
copyline = TMALLOC(char, strlen(start) + 1);
(void) memcpy(copyline, start, strlen(start) + 1);
if (verbose) {
printf("instance: %s itype: %s\n",
hdr->instance_name, hdr->instance_type);
}
/*
numgates gates, each gate has inwidth inputs and 1 output
inputs first
@ -2497,7 +2486,6 @@ static struct gate_instance *add_array_inout_timing_model(
name = TMALLOC(char, strlen(tok) + 1);
(void) memcpy(name, tok, strlen(tok) + 1);
inarr[k] = name;
if (verbose) { printf(" gate %d input(%d): %s\n", i, j, tok); }
k++;
}
}
@ -2507,7 +2495,6 @@ static struct gate_instance *add_array_inout_timing_model(
name = TMALLOC(char, strlen(tok) + 1);
(void) memcpy(name, tok, strlen(tok) + 1);
gip->enable = name;
if (verbose) { printf(" enable: %s\n", tok); }
}
/* outputs next */
outarr = TMALLOC(char *, numgates);
@ -2517,14 +2504,12 @@ static struct gate_instance *add_array_inout_timing_model(
name = TMALLOC(char, strlen(tok) + 1);
(void) memcpy(name, tok, strlen(tok) + 1);
outarr[i] = name;
if (verbose) { printf(" gate %d output: %s\n", i, tok); }
}
/* timing model last */
tok = strtok(NULL, " \t");
name = TMALLOC(char, strlen(tok) + 1);
(void) memcpy(name, tok, strlen(tok) + 1);
gip->tmodel = name;
if (verbose) { printf(" tmodel: %s\n", tok); }
tfree(copyline);
return gip;
}
@ -2534,7 +2519,7 @@ static struct gate_instance *add_gate_inout_timing_model(
{
char *tok, *copyline, *itype = hdr->instance_type;
int i, n1 = hdr->num1, n2 = hdr->num2, inwidth;
BOOL first = TRUE, tristate = FALSE, verbose = FALSE;
BOOL first = TRUE, tristate = FALSE;
struct gate_instance *gip = NULL;
char **inarr = NULL, **outarr = NULL, *name;
@ -2564,10 +2549,6 @@ static struct gate_instance *add_gate_inout_timing_model(
gip->num_outs = 1;
copyline = TMALLOC(char, strlen(start) + 1);
(void) memcpy(copyline, start, strlen(start) + 1);
if (verbose) {
printf("instance: %s itype: %s\n",
hdr->instance_name, hdr->instance_type);
}
/* inputs */
inarr = TMALLOC(char *, gip->num_ins);
gip->inputs = inarr;
@ -2581,7 +2562,6 @@ static struct gate_instance *add_gate_inout_timing_model(
name = TMALLOC(char, strlen(tok) + 1);
(void) memcpy(name, tok, strlen(tok) + 1);
inarr[i] = name;
if (verbose) { printf(" input(%d): %s\n", i, tok); }
}
/* enable for tristate */
if (tristate) {
@ -2589,7 +2569,6 @@ static struct gate_instance *add_gate_inout_timing_model(
name = TMALLOC(char, strlen(tok) + 1);
(void) memcpy(name, tok, strlen(tok) + 1);
gip->enable = name;
if (verbose) { printf(" enable: %s\n", tok); }
}
/* output */
assert(gip->num_outs == 1);
@ -2599,13 +2578,11 @@ static struct gate_instance *add_gate_inout_timing_model(
name = TMALLOC(char, strlen(tok) + 1);
(void) memcpy(name, tok, strlen(tok) + 1);
outarr[0] = name;
if (verbose) { printf(" output: %s\n", tok); }
/* timing model last */
tok = strtok(NULL, " \t");
name = TMALLOC(char, strlen(tok) + 1);
(void) memcpy(name, tok, strlen(tok) + 1);
gip->tmodel = name;
if (verbose) { printf(" tmodel: %s\n", tok); }
tfree(copyline);
return gip;
}