Add support for PSpice DLYLINE.
This commit is contained in:
parent
299d7c0dc6
commit
b67d895a7b
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue