Add support for PSpice DLYLINE.

This commit is contained in:
Brian Taylor 2023-08-05 10:34:16 -07:00
parent 299d7c0dc6
commit b67d895a7b
1 changed files with 92 additions and 6 deletions

View File

@ -10,7 +10,7 @@
using the previously stored delays.
Some limitations are:
No support for DLYLINE, CONSTRAINT, RAM, ROM, STIM, PLAs.
No support for CONSTRAINT, RAM, ROM, STIM, PLAs.
Approximations to the Pspice timing delays. Typical values for delays
are estimated. Pspice has a rich set of timing simulation features,
such as checks for setup/hold violations, minimum pulse width, and
@ -22,7 +22,7 @@
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
The delays for the different types (ugate, utgate, ueff, ugff, udly) are stored
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
@ -85,7 +85,8 @@ extern struct card* insert_new_line(
#define D_UP 16
#define D_DOWN 17
#define D_TRI 18
#define XSPICESZ 19
#define D_DLYLINE 19
#define XSPICESZ 20
/* structs for parsed gate U... instances */
struct instance_hdr {
@ -173,7 +174,7 @@ typedef struct s_xlate {
Xlatep next;
char *translated; // the translated instance line
char *delays; // the delays from the pspice timing model
char *utype; // pspice model type ugate, utgate, ueff, ugff
char *utype; // pspice model type ugate, utgate, ueff, ugff, udly
char *xspice; // xspice device type such as d_and, d_dff, etc.
char *tmodel; // timing model name of pspice instance or model
char *mname; // name of the xspice timing model of the instance
@ -472,6 +473,7 @@ static char *xspice_tab[XSPICESZ] = {
"d_pullup", // D_UP
"d_pulldown", // D_DOWN
"d_tristate", // D_TRI
"d_buffer", // D_DLYLINE uses buffer with transport delay
};
static char *find_xspice_for_delay(char *itype)
@ -502,6 +504,7 @@ static char *find_xspice_for_delay(char *itype)
case 'd': {
if (eq(itype, "dff")) { return xspice_tab[D_DFF]; }
if (eq(itype, "dltch")) { return xspice_tab[D_DLTCH]; }
if (eq(itype, "dlyline")) { return xspice_tab[D_DLYLINE]; }
break;
}
case 'i': {
@ -2793,7 +2796,7 @@ static char *larger_delay(char *delay1, char *delay2)
/* NOTE
The get_delays_...() functions calculate estimates of typical delays
from the Pspice ugate, utgate, ueff, and ugff timing models.
from the Pspice ugate, udly, utgate, ueff, and ugff timing models.
These functions are called from u_process_model(), and the delay strings
are added to the timing model Xlator by add_delays_to_model_xlator().
*/
@ -2836,6 +2839,26 @@ static char *get_delays_ugate(char *rem)
return delays;
}
static char *get_delays_udly(char *rem)
{
char *udelay, *delays = NULL;
struct timing_data *tdp1;
tdp1 = create_min_typ_max("dly", rem);
estimate_typ(tdp1);
udelay = get_estimate(tdp1);
if (udelay) {
delays = tprintf(
"(inertial_delay=false rise_delay = %s fall_delay = %s)",
udelay, udelay);
} else {
delays = tprintf(
"(inertial_delay=false rise_delay = 1.0e-12 fall_delay = 1.0e-12)");
}
delete_timing_data(tdp1);
return delays;
}
static char *get_delays_utgate(char *rem)
{
/* Return estimate of tristate delay (delay = val3) */
@ -3145,6 +3168,11 @@ static BOOL u_process_model(char *nline, char *original)
/* skip uio models */
retval = TRUE;
delays = NULL;
} else if (eq(utype, "udly")) {
delays = get_delays_udly(remainder);
add_delays_to_model_xlator((delays ? delays : ""),
utype, "", tmodel);
if (delays) { tfree(delays); }
} else {
retval = FALSE;
delays = NULL;
@ -3835,7 +3863,7 @@ static Xlatorp translate_pull(struct instance_hdr *hdr, char *start)
xspice = find_xspice_for_delay(itype);
newline = TMALLOC(char, strlen(start) + 1);
(void) memcpy(newline, start, strlen(start) + 1);
model_name = tprintf("d_%s_%s", iname, itype);
model_name = tprintf("d_a%s_%s", iname, itype);
for (i = 0; i < numpulls; i++) {
if (i == 0) {
tok = strtok(newline, " \t");
@ -3863,6 +3891,62 @@ end_of_function:
return xp;
}
static Xlatorp translate_dlyline(struct instance_hdr *hdr, char *start)
{
char *itype, *iname, *newline = NULL, *tok;
char *model_name = NULL, *tmodel = NULL;
Xlatorp xp = NULL;
Xlatep xdata = NULL;
DS_CREATE(statement, 128);
itype = hdr->instance_type;
iname = hdr->instance_name;
newline = TMALLOC(char, strlen(start) + 1);
(void) memcpy(newline, start, strlen(start) + 1);
model_name = tprintf("d_a%s_%s", iname, itype);
ds_clear(&statement);
/* input name */
tok = strtok(newline, " \t");
if (!tok) {
fprintf(stderr, "ERROR input missing from dlyline\n");
goto end_of_function;
}
ds_cat_printf(&statement, "a%s %s", iname, tok);
/* output name */
tok = strtok(NULL, " \t");
if (!tok) {
fprintf(stderr, "ERROR output missing from dlyline\n");
goto end_of_function;
}
ds_cat_printf(&statement, " %s %s", tok, model_name);
xp = create_xlator();
xdata = create_xlate_translated(ds_get_buf(&statement));
xp = add_xlator(xp, xdata);
/* tmodel */
tmodel = strtok(NULL, " \t");
if (!tmodel) {
fprintf(stderr, "ERROR timing model missing from dlyline\n");
delete_xlator(xp);
xp = NULL;
goto end_of_function;
}
if (!gen_timing_model(tmodel, "udly", "d_buffer", model_name, xp)) {
printf("WARNING unable to find tmodel %s for %s dlyline\n",
tmodel, model_name);
}
end_of_function:
if (model_name) { tfree(model_name); }
if (newline) { tfree(newline); }
delete_instance_hdr(hdr);
ds_free(&statement);
return xp;
}
static Xlatorp translate_ff_latch(struct instance_hdr *hdr, char *start)
{
/* If OK return Xlatorp else return NULL */
@ -4062,6 +4146,8 @@ BOOL u_process_instance(char *nline)
xp = translate_ff_latch(hdr, p1);
} else if (eq(itype, "pullup") || eq(itype, "pulldn")) {
xp = translate_pull(hdr, p1);
} else if (eq(itype, "dlyline")) {
xp = translate_dlyline(hdr, p1);
} else {
delete_instance_hdr(hdr);
if (ps_udevice_exit) {