diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index e7ae3b90b..c06184a01 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -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) {