Add default zero delay models d0_gate, d0_eff, d0_gff, d0_tgate. Use tprintf.

This commit is contained in:
Brian Taylor 2022-04-29 21:12:05 -07:00 committed by Holger Vogt
parent 5b332a1aba
commit 3e86af3989
1 changed files with 260 additions and 196 deletions

View File

@ -1,6 +1,7 @@
/* udevices.c translate PSPICE U* instances and timing models */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
@ -8,6 +9,7 @@
#include "ngspice/memory.h"
#include "ngspice/bool.h"
#include "ngspice/stringskip.h"
#include "ngspice/stringutil.h"
#include "ngspice/udevices.h"
/*
TODO check for name collisions with new names
@ -16,8 +18,6 @@
TODO investigate the method for generating model names
*/
#define BUFSIZE 2048
#define SMBUFSIZE 256
/* #define TRACE */
/* device types */
@ -254,7 +254,11 @@ static char *find_xspice_for_delay(char *itype)
return NULL;
}
/* Xlator and Xlate */
/*
Xlator and Xlate
Xlate struct data is stored in an Xlatorp list struct
Used to save translated instance and model statements
*/
static void delete_xlate(Xlatep p)
{
if (p) {
@ -426,16 +430,34 @@ 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;
void create_model_xlator(void)
{
Xlatep xdata;
model_xlatorp = create_xlator();
default_models = create_xlator();
/* .model d0_gate ugate () */
xdata = create_xlate("", "", "ugate", "", "d0_gate", "");
(void) add_xlator(default_models, xdata);
/* .model d0_gff ugff () */
xdata = create_xlate("", "", "ugff", "", "d0_gff", "");
(void) add_xlator(default_models, xdata);
/* .model d0_eff ueff () */
xdata = create_xlate("", "", "ueff", "", "d0_eff", "");
(void) add_xlator(default_models, xdata);
/* .model d0_tgate utgate () */
xdata = create_xlate("", "", "utgate", "", "d0_tgate", "");
(void) add_xlator(default_models, xdata);
}
void cleanup_model_xlator(void)
{
delete_xlator(model_xlatorp);
model_xlatorp = NULL;
delete_xlator(default_models);
default_models = NULL;
}
static Xlatep create_xlate_model(char *delays,
@ -444,14 +466,13 @@ static Xlatep create_xlate_model(char *delays,
return create_xlate("", delays, utype, xspice, tmodel, "");
}
static Xlatep find_in_model_xlator(Xlatep x)
static Xlatep find_in_xlator(Xlatep x, Xlatorp xlp)
{
Xlatep x1;
if (!x) { return NULL; }
if (!model_xlatorp) { return NULL; }
for (x1 = first_xlator(model_xlatorp); x1;
x1 = next_xlator(model_xlatorp)) {
if (!xlp) { return NULL; }
for (x1 = first_xlator(xlp); x1; x1 = next_xlator(xlp)) {
if (strcmp(x1->tmodel, x->tmodel) == 0 &&
strcmp(x1->utype, x->utype) == 0) {
if (strcmp(x1->xspice, x->xspice) == 0) {
@ -461,6 +482,15 @@ static Xlatep find_in_model_xlator(Xlatep x)
}
return NULL;
}
static Xlatep find_in_model_xlator(Xlatep x)
{
Xlatep x1;
x1 = find_in_xlator(x, model_xlatorp);
if (x1) { return x1; }
x1 = find_in_xlator(x, default_models);
return x1;
}
static void add_delays_to_model_xlator(char *delays,
char *utype, char *xspice, char *tmodel)
@ -475,8 +505,10 @@ static void add_delays_to_model_xlator(char *delays,
x = create_xlate_model(delays, utype, xspice, tmodel);
x1 = find_in_model_xlator(x);
if (x1) {
/*
printf("Already found timing model %s utype %s\n",
x1->tmodel, x1->utype);
*/
delete_xlate(x);
return;
}
@ -919,23 +951,17 @@ char *new_inverter(char *iname, char *node, Xlatorp xlp)
/* Return the name of the output of the new inverter */
/* tfree the returned string after it has been used ny the caller */
char *tmp = NULL;
size_t sz;
Xlatep xdata = NULL;
sz = 2*strlen(iname) + 3*strlen(node) + strlen("d_zero_inv99");
sz += 100; /* that should be enough */
tmp = TMALLOC(char, sz);
tmp[0] = '\0';
sprintf(tmp, "a%s_%s %s", iname, node, node);
sprintf(tmp + strlen(tmp), " not_%s_%s", iname, node);
sprintf(tmp + strlen(tmp), " d_zero_inv99");
tmp = tprintf("a%s_%s %s not_%s_%s d_zero_inv99",
iname, node, node, iname, node);
/* instantiate the new inverter */
/* e.g. au5_s1bar s1bar not_u5_s1bar d_zero_inv99 */
xdata = create_xlate_translated(tmp);
(void) add_xlator(xlp, xdata);
tmp[0] = '\0';
tfree(tmp);
/* the name of the inverter output */
sprintf(tmp, "not_%s_%s", iname, node);
tmp = tprintf("not_%s_%s", iname, node);
return tmp;
}
@ -951,10 +977,9 @@ static BOOL gen_timing_model(
xspice instance and model lines (not to be confused with model_xlatorp.
*/
Xlatep xin = NULL, xout = NULL, newdata;
char work[BUFSIZE];
char *s1;
BOOL retval;
printf("Need model %s %s for %s\n", tmodel, xspice, newname);
if (strcmp(utype, "ugff") == 0) {
xin = create_xlate_model("", utype, xspice, tmodel);
} else {
@ -963,14 +988,14 @@ static BOOL gen_timing_model(
xout = find_in_model_xlator(xin);
if (xout) {
/* Don't delete xout or the model_xlatorp will be corrupted */
//printf("Found tming model %s %s\n", xout->tmodel, xout->utype);
print_xlate(xout);
work[0] = '\0';
sprintf(work, ".model %s %s", newname, xspice);
if (xout->delays && strlen(xout->delays) > 0) {
sprintf(work + strlen(work), "%s", xout->delays);
s1 = tprintf(".model %s %s%s", newname, xspice, xout->delays);
} else {
s1 = tprintf(".model %s %s", newname, xspice);
}
newdata = create_xlate_translated(work);
newdata = create_xlate_translated(s1);
tfree(s1);
(void) add_xlator(xlp, newdata);
retval = TRUE;
} else {
@ -986,8 +1011,7 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip)
char *itype, *iname, **darr, **qarr, **qbarr;
char *preb, *clrb, *clk, *tmodel, *qout, *qbout;
int i, num_gates;
char work[BUFSIZE];
char smallbuf[SMBUFSIZE];
char *modelnm, *s1;
Xlatorp xxp = NULL;
Xlatep xdata = NULL;
BOOL need_preb_inv = FALSE, need_clrb_inv = FALSE;
@ -1019,31 +1043,27 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip)
clk = ip->clk;
tmodel = ip->tmodel;
smallbuf[0] = '\0';
/* model name, same for each dff */
sprintf(smallbuf, "d_a%s%s", iname, itype);
modelnm = tprintf("d_a%s%s", iname, itype);
for (i = 0; i < num_gates; i++) {
work[0] = '\0';
sprintf(work, "a%s_%d", iname, i);
sprintf(work + strlen(work), " %s %s %s %s",
darr[i], clk, preb, clrb);
qout = qarr[i];
if (strcmp(qout, "$d_nc") == 0) {
qout = "NULL";
}
sprintf(work + strlen(work), " %s", qout);
qbout = qbarr[i];
if (strcmp(qbout, "$d_nc") == 0) {
qbout = "NULL";
}
sprintf(work + strlen(work), " %s", qbout);
sprintf(work + strlen(work), " %s", smallbuf);
xdata = create_xlate_instance(work, " d_dff", tmodel, smallbuf);
s1 = tprintf( "a%s_%d %s %s %s %s %s %s %s",
iname, i, darr[i], clk, preb, clrb, qout, qbout, modelnm
);
xdata = create_xlate_instance(s1, " d_dff", tmodel, modelnm);
xxp = add_xlator(xxp, xdata);
tfree(s1);
}
if (!gen_timing_model(tmodel, "ueff", "d_dff", smallbuf, xxp)) {
if (!gen_timing_model(tmodel, "ueff", "d_dff", modelnm, xxp)) {
printf("WARNING unable to find tmodel %s for %s d_dff\n",
tmodel, smallbuf);
tmodel, modelnm);
}
if (need_preb_inv || need_clrb_inv) {
xdata = create_xlate_translated(".model d_zero_inv99 d_inverter");
@ -1051,6 +1071,7 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip)
}
if (need_preb_inv) { tfree(preb); }
if (need_clrb_inv) { tfree(clrb); }
tfree(modelnm);
return xxp;
return NULL;
@ -1061,8 +1082,7 @@ static Xlatorp gen_jkff_instance(struct jkff_instance *ip)
char *itype, *iname, **jarr, **karr, **qarr, **qbarr;
char *preb, *clrb, *clkb, *tmodel, *qout, *qbout;
int i, num_gates;
char work[BUFSIZE];
char smallbuf[SMBUFSIZE];
char *modelnm, *s1;
Xlatorp xxp = NULL;
Xlatep xdata = NULL;
BOOL need_preb_inv = FALSE, need_clrb_inv = FALSE;
@ -1098,39 +1118,36 @@ static Xlatorp gen_jkff_instance(struct jkff_instance *ip)
clkb = new_inverter(iname, clkb, xxp);
tmodel = ip->tmodel;
smallbuf[0] = '\0';
/* model name, same for each latch */
sprintf(smallbuf, "d_a%s%s", iname, itype);
modelnm = tprintf("d_a%s%s", iname, itype);
for (i = 0; i < num_gates; i++) {
work[0] = '\0';
sprintf(work, "a%s_%d", iname, i);
sprintf(work + strlen(work), " %s %s %s %s %s",
jarr[i], karr[i], clkb, preb, clrb);
qout = qarr[i];
if (strcmp(qout, "$d_nc") == 0) {
qout = "NULL";
}
sprintf(work + strlen(work), " %s", qout);
qbout = qbarr[i];
if (strcmp(qbout, "$d_nc") == 0) {
qbout = "NULL";
}
sprintf(work + strlen(work), " %s %s", qbout, smallbuf);
xdata = create_xlate_instance(work, " d_jkff", tmodel, smallbuf);
s1 = tprintf("a%s_%d %s %s %s %s %s %s %s %s",
iname, i, jarr[i], karr[i], clkb, preb, clrb, qout, qbout, modelnm
);
xdata = create_xlate_instance(s1, " d_jkff", tmodel, modelnm);
xxp = add_xlator(xxp, xdata);
tfree(s1);
}
if (!gen_timing_model(tmodel, "ueff", "d_jkff", smallbuf, xxp)) {
if (!gen_timing_model(tmodel, "ueff", "d_jkff", modelnm, xxp)) {
printf("WARNING unable to find tmodel %s for %s d_jkff\n",
tmodel, smallbuf);
tmodel, modelnm);
}
xdata = create_xlate_translated(".model d_zero_inv99 d_inverter");
xxp = add_xlator(xxp, xdata);
tfree(clkb);
if (need_preb_inv) { tfree(preb); }
if (need_clrb_inv) { tfree(clrb); }
tfree(modelnm);
return xxp;
return NULL;
}
static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
@ -1138,8 +1155,7 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
char *itype, *iname, **darr, **qarr, **qbarr;
char *preb, *clrb, *gate, *tmodel, *qout, *qbout;
int i, num_gates;
char work[BUFSIZE];
char smallbuf[SMBUFSIZE];
char *modelnm, *s1, *s2, *s3;
Xlatorp xxp = NULL;
Xlatep xdata = NULL;
BOOL need_preb_inv = FALSE, need_clrb_inv = FALSE;
@ -1169,35 +1185,35 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
}
gate = ip->gate;
tmodel = ip->tmodel;
smallbuf[0] = '\0';
/* model name, same for each latch */
sprintf(smallbuf, "d_a%s%s", iname, itype);
modelnm = tprintf("d_a%s%s", iname, itype);
for (i = 0; i < num_gates; i++) {
work[0] = '\0';
sprintf(work, "a%s_%d", iname, i);
sprintf(work + strlen(work), " %s %s %s %s",
darr[i], gate, preb, clrb);
qout = qarr[i];
if (strcmp(qout, "$d_nc") == 0) {
/* NULL not allowed??? */
sprintf(work + strlen(work), " nco%s_%d", iname, i);
s1 = tprintf("a%s_%d %s %s %s %s nco%s_%d",
iname, i, darr[i], gate, preb, clrb, iname, i);
} else {
sprintf(work + strlen(work), " %s", qout);
s1 = tprintf("a%s_%d %s %s %s %s %s",
iname, i, darr[i], gate, preb, clrb, qout);
}
qbout = qbarr[i];
if (strcmp(qbout, "$d_nc") == 0) {
/* NULL not allowed??? */
sprintf(work + strlen(work), " ncn%s_%d", iname, i);
s2 = tprintf(" ncn%s_%d %s", iname, i, modelnm);
} else {
sprintf(work + strlen(work), " %s", qbout);
s2 = tprintf(" %s %s", qbout, modelnm);
}
sprintf(work + strlen(work), " %s", smallbuf);
xdata = create_xlate_instance(work, " d_dlatch", tmodel, smallbuf);
s3 = tprintf("%s%s", s1, s2);
xdata = create_xlate_instance(s3, " d_dlatch", tmodel, modelnm);
xxp = add_xlator(xxp, xdata);
tfree(s1);
tfree(s2);
tfree(s3);
}
if (!gen_timing_model(tmodel, "ugff", "d_dlatch", smallbuf, xxp)) {
if (!gen_timing_model(tmodel, "ugff", "d_dlatch", modelnm, xxp)) {
printf("WARNING unable to find tmodel %s for %s d_dlatch\n",
tmodel, smallbuf);
tmodel, modelnm);
}
if (need_preb_inv || need_clrb_inv) {
xdata = create_xlate_translated(".model d_zero_inv99 d_inverter");
@ -1205,6 +1221,7 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
}
if (need_preb_inv) { tfree(preb); }
if (need_clrb_inv) { tfree(clrb); }
tfree(modelnm);
return xxp;
}
@ -1212,18 +1229,18 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
static Xlatorp gen_gate_instance(struct gate_instance *gip)
{
char **inarr, **outarr, *itype, *iname, *enable, *tmodel;
char *work, *xspice = NULL, *connector = NULL;
char *xspice = NULL, *connector = NULL;
BOOL vector = FALSE, tristate_gate = FALSE, simple_gate = FALSE;
BOOL tristate_array = FALSE, simple_array = FALSE;
BOOL add_tristate = FALSE;
char smallbuf[SMBUFSIZE], modelbuf[SMBUFSIZE];
char *modelnm = NULL, *startvec = NULL, *endvec = NULL;
char *input_buf = NULL;
int i, j, k, width, num_gates, num_ins, num_outs;
size_t sz;
Xlatorp xxp = NULL;
Xlatep xdata = NULL;
if (!gip) { return NULL; }
smallbuf[0] = '\0';
itype = gip->hdrp->instance_type;
iname = gip->hdrp->instance_name;
inarr = gip->inputs;
@ -1238,6 +1255,7 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
vector = has_vector_inputs(itype);
if (num_gates == 1) {
char *inst_begin = NULL;
assert(num_outs == 1);
simple_gate = is_gate(itype);
tristate_gate = is_tristate(itype);
@ -1256,53 +1274,76 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
}
assert(xspice);
xxp = create_xlator();
work = TMALLOC(char, BUFSIZE);
work[0] = '\0';
/* Now build the instance name and inputs section */
/* instance name */
sprintf(work, "a%s ", iname);
if (vector) { strcat(work, "["); }
/* inputs */
for (i = 0; i < width; i++) {
sprintf(work + strlen(work), " %s", inarr[i]);
if (vector) {
startvec = "[";
endvec = " ]";
} else {
startvec = "";
endvec = "";
}
if (vector) { strcat(work, " ]"); }
/* inputs */
/* First calculate the space */
sz = 0;
for (i = 0; i < width; i++) {
sz += strlen(inarr[i]) + 4; // Extra 4 spaces separating
}
input_buf = TMALLOC(char, sz);
input_buf[0] = '\0';
for (i = 0; i < width; i++) {
sprintf(input_buf + strlen(input_buf), " %s", inarr[i]);
}
/* instance name and inputs */
/* add the tristate enable if required on original */
if (enable) {
assert(tristate_gate);
if (!add_tristate) {
sprintf(work + strlen(work)," %s", enable);
/* Warning: changing the format string affects input_buf sz */
inst_begin = tprintf("a%s %s%s%s %s",
iname, startvec, input_buf, endvec, enable);
} else {
/* Warning: changing the format string affects input_buf sz */
inst_begin = tprintf("a%s %s%s%s",
iname, startvec, input_buf, endvec);
}
} else {
/* Warning: changing the format string affects input_buf sz */
inst_begin = tprintf("a%s %s%s%s",
iname, startvec, input_buf, endvec);
}
tfree(input_buf);
/* connector if required for tristate */
sprintf(smallbuf, "a%s_%s", iname, outarr[0]);
connector = TMALLOC(char, strlen(smallbuf) + 1);
connector[0] = '\0';
(void) memcpy(connector, smallbuf, strlen(smallbuf) + 1);
connector = tprintf("a%s_%s", iname, outarr[0]);
/* keep a copy of the model name of original gate */
modelbuf[0] = '\0';
sprintf(modelbuf, "d_a%s%s", iname, itype);
modelnm = tprintf("d_a%s%s", iname, itype);
if (!add_tristate) {
char *instance_stmt = NULL;
/* add output + model name => translated instance */
sprintf(work + strlen(work), " %s %s", outarr[0], modelbuf);
xdata = create_xlate_instance(work, xspice, tmodel, modelbuf);
instance_stmt = tprintf("%s %s %s",
inst_begin, outarr[0], modelnm);
xdata = create_xlate_instance(instance_stmt,
xspice, tmodel, modelnm);
xxp = add_xlator(xxp, xdata);
tfree(instance_stmt);
if (simple_gate) {
if (!gen_timing_model(tmodel, "ugate", xspice,
modelbuf, xxp)) {
modelnm, xxp)) {
printf("WARNING unable to find tmodel %s for %s %s\n",
tmodel, modelbuf, xspice);
tmodel, modelnm, xspice);
}
} else { /* must be trstate gate buf3 */
if (!gen_timing_model(tmodel, "utgate", xspice,
modelbuf, xxp)) {
modelnm, xxp)) {
printf("WARNING unable to find tmodel %s for %s %s\n",
tmodel, modelbuf, xspice);
tmodel, modelnm, xspice);
}
}
} else {
char *new_model_nm = NULL;
char *new_stmt = NULL;
/*
Use connector as original gate output and tristate input;
tristate has original gate output and utgate delay;
@ -1310,34 +1351,39 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
Complete the translation of the original gate adding
the connector as output + model name.
*/
sprintf(work + strlen(work), " %s %s", connector, modelbuf);
xdata = create_xlate_instance(work, xspice, "", modelbuf);
new_stmt = tprintf("%s %s %s", inst_begin, connector, modelnm);
xdata = create_xlate_instance(new_stmt, xspice, "", modelnm);
xxp = add_xlator(xxp, xdata);
tfree(new_stmt);
/* new model statement e.g. .model d_au2nand3 d_nand */
work[0] = '\0';
sprintf(work, ".model %s %s", modelbuf, xspice);
xdata = create_xlate_translated(work);
new_stmt = tprintf(".model %s %s", modelnm, xspice);
xdata = create_xlate_translated(new_stmt);
xxp = add_xlator(xxp, xdata);
tfree(new_stmt);
/* now the added tristate */
work[0] = '\0';
modelbuf[0] = '\0';
/* model name of added tristate */
sprintf(modelbuf, "d_a%stribuf", iname);
sprintf(work, "a%s_tri %s %s %s %s", iname, connector,
enable, outarr[0], modelbuf);
xdata = create_xlate_instance(work, "d_tristate", tmodel, modelbuf);
new_model_nm = tprintf("d_a%stribuf", iname);
new_stmt = tprintf("a%s_tri %s %s %s %s",
iname, connector, enable, outarr[0], new_model_nm);
xdata = create_xlate_instance(new_stmt, "d_tristate",
tmodel, new_model_nm);
xxp = add_xlator(xxp, xdata);
tfree(new_stmt);
if (!gen_timing_model(tmodel, "utgate", "d_tristate",
modelbuf, xxp)) {
new_model_nm, xxp)) {
printf("WARNING unable to find tmodel %s for %s %s\n",
tmodel, modelbuf, xspice);
tmodel, new_model_nm, xspice);
}
tfree(new_model_nm);
}
tfree(work);
tfree(connector);
tfree(modelnm);
tfree(inst_begin);
return xxp;
} else {
char *primary_model = NULL, *s1 = NULL, *s2 = NULL, *s3 = NULL;
int ksave;
/* arrays of gates */
/* NOTE (n)and3a, (n)or3a, (n)xora types are not supported */
assert(num_outs == num_gates);
@ -1363,104 +1409,122 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
}
assert(xspice);
xxp = create_xlator();
sz = BUFSIZE;
work = TMALLOC(char, sz);
k = 0;
connector = NULL;
if (vector) {
startvec = "[";
endvec = " ]";
} else {
startvec = "";
endvec = "";
}
/* model name, same for all primary gates */
modelbuf[0] = '\0';
sprintf(modelbuf, "d_a%s%s", iname, itype);
primary_model = tprintf("d_a%s%s", iname, itype);
for (i = 0; i < num_gates; i++) {
work[0] = '\0';
/* create new instance name for primary gate */
sprintf(work, "a%s_%d ", iname, i);
if (vector) { strcat(work, "["); }
/* inputs */
/* First calculate the space */
ksave = k;
sz = 0;
for (j = 0; j < width; j++) {
/* inputs for primary gate */
sprintf(work + strlen(work), " %s", inarr[k]);
sz += strlen(inarr[k]) + 4; // Extra 4 spaces separating
k++;
}
if (vector) { strcat(work, " ]"); }
k = ksave;
input_buf = TMALLOC(char, sz);
input_buf[0] = '\0';
for (j = 0; j < width; j++) {
/* inputs for primary gate */
/* Warning: changing the format string affects input_buf sz */
sprintf(input_buf + strlen(input_buf), " %s", inarr[k]);
k++;
}
/* create new instance name for primary gate */
if (enable) {
if (!add_tristate) {
sprintf(work + strlen(work)," %s", enable);
s1 = tprintf("a%s_%d %s%s%s %s",
iname, i, startvec, input_buf, endvec, enable);
} else {
s1 = tprintf("a%s_%d %s%s%s",
iname, i, startvec, input_buf, endvec);
/* connector if required for tristate */
sprintf(smallbuf, "a%s_%d_%s", iname, i, outarr[i]);
connector = TMALLOC(char, strlen(smallbuf) + 1);
connector[0] = '\0';
(void) memcpy(connector, smallbuf, strlen(smallbuf) + 1);
connector = tprintf("a%s_%d_%s", iname, i, outarr[i]);
}
} else {
s1 = tprintf("a%s_%d %s%s%s",
iname, i, startvec, input_buf, endvec);
}
tfree(input_buf);
/* output of primary gate */
if (add_tristate) {
sprintf(work + strlen(work), " %s", connector);
s2 = tprintf(" %s %s", connector, primary_model);
} else {
sprintf(work + strlen(work), " %s", outarr[i]);
s2 = tprintf(" %s %s", outarr[i], primary_model);
}
/* translated instance */
sprintf(work + strlen(work), " %s", modelbuf);
s3 = tprintf("%s%s", s1, s2);
if (add_tristate) {
xdata = create_xlate_instance(work, xspice, "", modelbuf);
xdata = create_xlate_instance(s3, xspice, "", primary_model);
xxp = add_xlator(xxp, xdata);
} else {
xdata = create_xlate_instance(work, xspice, tmodel, modelbuf);
xdata = create_xlate_instance(s3, xspice, tmodel,
primary_model);
xxp = add_xlator(xxp, xdata);
}
tfree(s1);
tfree(s2);
tfree(s3);
if (!add_tristate) {
if (tristate_array) {
assert(strcmp(xspice, "d_tristate") == 0);
assert(strcmp(itype, "buf3a") == 0);
if (i == 0 && !gen_timing_model(tmodel, "utgate",
xspice, modelbuf, xxp)) {
xspice, primary_model, xxp)) {
printf("WARNING unable to find tmodel %s for %s %s\n",
tmodel, modelbuf, xspice);
tmodel, primary_model, xspice);
}
} else {
if (i == 0 && !gen_timing_model(tmodel, "ugate",
xspice, modelbuf, xxp)) {
xspice, primary_model, xxp)) {
printf("WARNING unable to find tmodel %s for %s %s\n",
tmodel, modelbuf, xspice);
tmodel, primary_model, xspice);
}
}
}
if (add_tristate) {
char *s1 = NULL, *modelnm = NULL;
if (i == 0) {
/* Zero delay model for all original array instances */
work[0] = '\0';
sprintf(work, ".model %s %s", modelbuf, xspice);
xdata = create_xlate_translated(work);
s1 = tprintf(".model %s %s", primary_model, xspice);
xdata = create_xlate_translated(s1);
xxp = add_xlator(xxp, xdata);
tfree(s1);
}
work[0] = '\0';
smallbuf[0] = '\0';
/* model name of added tristate */
sprintf(smallbuf, "d_a%stribuf", iname);
modelnm = tprintf("d_a%stribuf", iname);
/*
instance name of added tristate, connector,
enable, original primary gate output, timing model.
*/
sprintf(work, "a%s_%d_tri %s %s %s %s", iname, i, connector,
enable, outarr[i], smallbuf);
xdata = create_xlate_instance(work, "d_tristate",
tmodel, smallbuf);
s1 = tprintf("a%s_%d_tri %s %s %s %s", iname, i, connector,
enable, outarr[i], modelnm);
xdata = create_xlate_instance(s1, "d_tristate",
tmodel, modelnm);
xxp = add_xlator(xxp, xdata);
tfree(s1);
if (i == 0 && !gen_timing_model(tmodel, "utgate",
"d_tristate", smallbuf, xxp)) {
"d_tristate", modelnm, xxp)) {
printf("WARNING unable to find tmodel %s for %s %s\n",
tmodel, smallbuf, "d_tristate");
tmodel, modelnm, "d_tristate");
}
tfree(modelnm);
tfree(connector);
}
if (strlen(work) > BUFSIZE/2) {
tfree(work);
sz += BUFSIZE;
printf("TMALLOC work size %lu\n", sz);
work = TMALLOC(char, sz);
}
}
tfree(work);
tfree(primary_model);
return xxp;
}
return NULL;
@ -1555,7 +1619,6 @@ static void estimate_typ(struct timing_data *tdp)
char *min, *typ, *max;
float valmin, valmax, average;
char *units1, *units2;
static char avebuf[SMBUFSIZE];
if (!tdp) { return; }
min = tdp->min;
@ -1577,12 +1640,10 @@ static void estimate_typ(struct timing_data *tdp)
valmin = strtof(tmpmin, &units1);
valmax = strtof(tmpmax, &units2);
average = (valmin + valmax) / 2.0;
sprintf(avebuf, "%.2f%s", average, units2);
tdp->ave = tprintf("%.2f%s", average, units2);
if (strcmp(units1, units2) != 0) {
printf("WARNING units do not match\n");
}
tdp->ave = TMALLOC(char, strlen(avebuf) + 1);
(void) memcpy(tdp->ave, avebuf, strlen(avebuf) + 1);
tdp->estimate = EST_AVE;
return;
}
@ -1618,8 +1679,6 @@ static char *get_estimate(struct timing_data *tdp)
static char *get_delays_ugate(char *rem, char *d_name)
{
char *rising, *falling, *delays = NULL;
int count;
char work_buf[BUFSIZE];
struct timing_data *tdp1, *tdp2;
tdp1 = create_min_typ_max("tplh", rem);
@ -1630,11 +1689,8 @@ static char *get_delays_ugate(char *rem, char *d_name)
falling = get_estimate(tdp2);
if (rising && falling) {
if (strlen(rising) > 0 && strlen(falling) > 0) {
count = sprintf(work_buf, "(rise_delay = %s fall_delay = %s)",
delays = tprintf("(rise_delay = %s fall_delay = %s)",
rising, falling);
count++;
delays = TMALLOC(char, count);
(void) memcpy(delays, work_buf, count);
}
}
delete_timing_data(tdp1);
@ -1646,8 +1702,6 @@ static char *get_delays_utgate(char *rem, char *d_name)
{
/* Return estimate of tristate delay (delay = val3) */
char *rising, *falling, *delays = NULL;
int count;
char work_buf[BUFSIZE];
struct timing_data *tdp1, *tdp2;
tdp1 = create_min_typ_max("tplh", rem);
@ -1658,10 +1712,7 @@ static char *get_delays_utgate(char *rem, char *d_name)
falling = get_estimate(tdp2);
if (rising && falling) {
if (strlen(rising) > 0 && strlen(falling) > 0) {
count = sprintf(work_buf, "(delay = %s)", rising);
count++;
delays = TMALLOC(char, count);
(void) memcpy(delays, work_buf, count);
delays = tprintf("(delay = %s)", rising);
}
}
delete_timing_data(tdp1);
@ -1674,8 +1725,6 @@ static char *get_delays_ueff(char *rem, char *d_name)
char *delays = NULL;
char *clkqrise, *clkqfall, *pcqrise, *pcqfall;
char *clkd, *setd, *resetd;
int count;
char work_buf[BUFSIZE];
struct timing_data *tdp1, *tdp2, *tdp3, *tdp4;
tdp1 = create_min_typ_max("tpclkqlh", rem);
@ -1704,24 +1753,21 @@ static char *get_delays_ueff(char *rem, char *d_name)
setd = resetd = pcqfall;
}
if (clkd && setd) {
count = sprintf(work_buf, "(clk_delay = %s "
delays = tprintf("(clk_delay = %s "
"set_delay = %s reset_delay = %s "
"rise_delay = 1.0ns fall_delay = 2.0ns)",
clkd, setd, resetd);
} else if (clkd) {
count = sprintf(work_buf, "(clk_delay = %s "
delays = tprintf("(clk_delay = %s "
"rise_delay = 1.0ns fall_delay = 2.0ns)",
clkd);
} else if (setd) {
count = sprintf(work_buf, "(set_delay = %s reset_delay = %s "
delays = tprintf("(set_delay = %s reset_delay = %s "
"rise_delay = 1.0ns fall_delay = 2.0ns)",
setd, resetd);
} else {
count = sprintf(work_buf, "(rise_delay = 1.0ns fall_delay = 2.0ns)");
delays = tprintf("(rise_delay = 1.0ns fall_delay = 2.0ns)");
}
count++;
delays = TMALLOC(char, count);
(void) memcpy(delays, work_buf, count);
delete_timing_data(tdp1);
delete_timing_data(tdp2);
delete_timing_data(tdp3);
@ -1734,7 +1780,7 @@ static char *get_delays_ugff(char *rem, char *d_name)
char *delays = NULL, *dname;
char *tpdqlh, *tpdqhl, *tpgqlh, *tpgqhl, *tppcqlh, *tppcqhl;
char *d_delay, *enab, *setd, *resetd;
char work_buf[BUFSIZE];
char *s1, *s2;
struct timing_data *tdp1, *tdp2, *tdp3, *tdp4, *tdp5, *tdp6;
if (strcmp(d_name, "d_dlatch") == 0) {
@ -1762,25 +1808,30 @@ static char *get_delays_ugff(char *rem, char *d_name)
tdp6 = create_min_typ_max("tppcqhl", rem);
estimate_typ(tdp6);
tppcqhl = get_estimate(tdp6);
work_buf[0] = '\0';
strcpy(work_buf, "(");
d_delay = NULL;
if (tpdqlh && strlen(tpdqlh) > 0) {
d_delay = tpdqlh;
} else if (tpdqhl && strlen(tpdqhl) > 0) {
d_delay = tpdqhl;
}
if (d_delay) {
sprintf(&work_buf[strlen(work_buf)], "%s = %s ", dname, d_delay);
}
enab = NULL;
if (tpgqlh && strlen(tpgqlh) > 0) {
enab = tpgqlh;
} else if (tpgqhl && strlen(tpgqhl) > 0) {
enab = tpgqhl;
}
s1 = NULL;
if (enab) {
sprintf(&work_buf[strlen(work_buf)], "enable_delay = %s ", enab);
if (d_delay) {
s1 = tprintf("%s = %s enable_delay = %s ",
dname, d_delay, enab);
} else {
s1 = tprintf("enable_delay = %s ", enab);
}
} else {
if (d_delay) {
s1 = tprintf("%s = %s ", dname, d_delay);
}
}
setd = NULL;
resetd = NULL;
@ -1790,13 +1841,19 @@ static char *get_delays_ugff(char *rem, char *d_name)
setd = resetd = tppcqhl;
}
if (setd) {
sprintf(&work_buf[strlen(work_buf)],
"set_delay = %s reset_delay = %s ", setd, resetd);
s2 = tprintf("set_delay = %s reset_delay = %s "
"rise_delay = 1.0ns fall_delay = 2.0ns)",
setd, resetd);
} else {
s2 = tprintf("rise_delay = 1.0ns fall_delay = 2.0ns)");
}
sprintf(&work_buf[strlen(work_buf)],
"rise_delay = 1.0ns fall_delay = 2.0ns)");
delays = TMALLOC(char, strlen(work_buf) + 1);
(void) memcpy(delays, work_buf, strlen(work_buf) + 1);
if (s1) {
delays = tprintf("(%s%s", s1, s2);
tfree(s1);
} else {
delays = tprintf("(%s", s2);
}
tfree(s2);
delete_timing_data(tdp1);
delete_timing_data(tdp2);
delete_timing_data(tdp3);
@ -1830,45 +1887,50 @@ static BOOL u_process_model(char *nline, char *original,
if (remainder) {
if (strcmp(utype, "ugate") == 0) {
delays = get_delays_ugate(remainder, xspice);
printf("<%s>\n", delays);
if (delays) {
printf("<%s>\n", delays);
add_delays_to_model_xlator(delays, utype, "", tmodel);
} else {
printf("<(null)>\n");
add_delays_to_model_xlator("", utype, "", tmodel);
}
if (delays) { tfree(delays); }
} else if (strcmp(utype, "utgate") == 0) {
delays = get_delays_utgate(remainder, xspice);
printf("<%s>\n", delays);
if (delays) {
printf("<%s>\n", delays);
add_delays_to_model_xlator(delays, utype, "", tmodel);
} else {
printf("<(null)>\n");
add_delays_to_model_xlator("", utype, "", tmodel);
}
if (delays) { tfree(delays); }
} else if (strcmp(utype, "ueff") == 0) {
delays = get_delays_ueff(remainder, xspice);
printf("<%s>\n", delays);
if (delays) {
printf("<%s>\n", delays);
add_delays_to_model_xlator(delays, utype, "", tmodel);
} else {
printf("<(null)>\n");
add_delays_to_model_xlator("", utype, "", tmodel);
}
if (delays) { tfree(delays); }
} else if (strcmp(utype, "ugff") == 0) {
delays = get_delays_ugff(remainder, "d_dlatch");
printf("<%s>\n", delays);
if (delays) {
printf("<%s>\n", delays);
add_delays_to_model_xlator(delays, utype, "d_dlatch", tmodel);
} else {
printf("<(null)>\n");
add_delays_to_model_xlator("", utype, "d_dlatch", tmodel);
}
if (delays) { tfree(delays); }
delays = get_delays_ugff(remainder, "d_srlatch");
printf("<%s>\n", delays);
if (delays) {
printf("<%s>\n", delays);
add_delays_to_model_xlator(delays, utype, "d_srlatch", tmodel);
} else {
printf("<(null)>\n");
add_delays_to_model_xlator("", utype, "d_srlatch", tmodel);
}
if (delays) { tfree(delays); }
@ -2367,7 +2429,9 @@ BOOL u_process_instance(char *nline)
retval = FALSE;
}
if (xp) {
//interpret_xlator(xp, TRUE);
#ifdef TRACE
interpret_xlator(xp, TRUE);
#endif
delete_xlator(xp);
}
return retval;