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:
parent
701ed7beb0
commit
63cec9668c
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue