Handle cases where logicexp has a timing model but no pindly. This is rare, only 22 tests from the digital libraries. Move digital examples, add missing .spiceint file.

This commit is contained in:
Brian Taylor 2022-11-26 09:40:35 -08:00 committed by Holger Vogt
parent de2280ca73
commit 44c69f5bf5
6 changed files with 79 additions and 5 deletions

View File

@ -0,0 +1 @@
set ngbehavior=ltpsa

View File

@ -292,6 +292,32 @@ static char *lex_gate_name(int c, BOOL not)
return buf;
}
static char *tmodel_gate_name(int c, BOOL not)
{
/* Returns an XSPICE model name for the case where
logicexp does not have a corresponding pindly
but does have a UGATE timing model (not d0_gate).
*/
static char buf[32];
switch (c) {
case '&':
if (not)
sprintf(buf, "dxspice_dly_nand");
else
sprintf(buf, "dxspice_dly_and");
break;
case '|':
if (not)
sprintf(buf, "dxspice_dly_nor");
else
sprintf(buf, "dxspice_dly_or");
break;
default:
return NULL;
}
return buf;
}
static int lex_gate_op(int c)
{
switch (c) {
@ -584,6 +610,7 @@ static int adepth = 0;
static int max_adepth = 0;
static DSTRING d_curr_line;
static int number_of_instances = 0;
static BOOL use_tmodel_delays = FALSE;
static BOOL inverters_needed(void)
{
@ -888,7 +915,7 @@ static PTABLE optimize_gen_tab(PTABLE pt)
{
/* This function compacts the gen_tab, returning a new PTABLE.
Aliases are transformed and removed as described below.
Usually, optimized_gen_tab is called a second time on the
Usually, optimize_gen_tab is called a second time on the
PTABLE created by the first call. The algorithm here will
only transform one level of aliases.
*/
@ -1131,7 +1158,7 @@ static void gen_gates(PTABLE gate_tab, SYM_TAB parser_symbols)
tok_count = 0;
gate_op = 0;
in_count = 0;
while (val != '\0') {
while (val != '\0') { // while val loop
tok_count++;
if (val == LEX_ID) {
idnum++;
@ -1170,13 +1197,33 @@ static void gen_gates(PTABLE gate_tab, SYM_TAB parser_symbols)
goto quick_return;
}
val = lexer_scan(lxr);
}
} // end while val loop
if (in_count == 1) { // buffer or inverter
if (gate_op != 0) goto quick_return;
ds_cat_str(&gate_name, lex_gate_name('~', found_tilde));
} else if (in_count >= 2) { // AND, OR. XOR and inverses
if (gate_op == 0) goto quick_return;
ds_cat_str(&gate_name, lex_gate_name(gate_op, found_tilde));
if (use_tmodel_delays) {
/* This is the case when logicexp has a UGATE
timing model (not d0_gate) and no pindly.
*/
SYM_TAB entry = NULL;
char *nm1 = 0;
entry = member_sym_tab(ds_get_buf(&out_name), parser_symbols);
if (entry && (entry->attribute & SYM_OUTPUT)) {
nm1 = tmodel_gate_name(gate_op, found_tilde);
if (nm1) {
ds_cat_str(&gate_name, nm1);
}
}
if (!nm1) {
nm1 = lex_gate_name(gate_op, found_tilde);
ds_cat_str(&gate_name, nm1);
}
} else {
ds_cat_str(&gate_name, lex_gate_name(gate_op, found_tilde));
}
} else {
goto quick_return;
}
@ -1537,7 +1584,19 @@ BOOL f_logicexp(char *line)
/* timing model */
t = lex_scan();
if (!expect_token(t, LEX_ID, NULL, TRUE, 12)) goto error_return;
//printf("TMODEL: %s\n", parse_lexer->lexer_buf);
if (!eq(parse_lexer->lexer_buf, "d0_gate")) {
u_add_logicexp_model(parse_lexer->lexer_buf,
"d_and", "dxspice_dly_and");
u_add_logicexp_model(parse_lexer->lexer_buf,
"d_nand", "dxspice_dly_nand");
u_add_logicexp_model(parse_lexer->lexer_buf,
"d_or", "dxspice_dly_or");
u_add_logicexp_model(parse_lexer->lexer_buf,
"d_nor", "dxspice_dly_nor");
use_tmodel_delays = TRUE;
} else {
use_tmodel_delays = FALSE;
}
(void) add_sym_tab_entry(parse_lexer->lexer_buf,
SYM_TMODEL, &parse_lexer->lexer_sym_tab);
ret_val = bparse(line, FALSE);

View File

@ -777,6 +777,19 @@ void u_add_instance(char *str)
}
}
static BOOL gen_timing_model(
char *tmodel, char *utype, char *xspice, char *newname, Xlatorp xlp);
void u_add_logicexp_model(char *tmodel, char *xspice_gate, char *model_name)
{
Xlatorp xlp = NULL;
xlp = create_xlator();
if (gen_timing_model(tmodel, "ugate", xspice_gate, model_name, xlp)) {
append_xlator(translated_p, xlp);
}
delete_xlator(xlp);
}
void initialize_udevice(char *subckt_line)
{
Xlatep xdata;

View File

@ -8,5 +8,6 @@ void initialize_udevice(char *subckt_line);
struct card *replacement_udevice_cards(void);
void cleanup_udevice(void);
void u_add_instance(char *str);
void u_add_logicexp_model(char *tmodel, char *xspice_gate, char *model_name);
#endif