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:
parent
cd883d23d6
commit
7ff8f3773f
|
|
@ -0,0 +1 @@
|
||||||
|
set ngbehavior=ltpsa
|
||||||
|
|
@ -292,6 +292,32 @@ static char *lex_gate_name(int c, BOOL not)
|
||||||
return buf;
|
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)
|
static int lex_gate_op(int c)
|
||||||
{
|
{
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|
@ -584,6 +610,7 @@ static int adepth = 0;
|
||||||
static int max_adepth = 0;
|
static int max_adepth = 0;
|
||||||
static DSTRING d_curr_line;
|
static DSTRING d_curr_line;
|
||||||
static int number_of_instances = 0;
|
static int number_of_instances = 0;
|
||||||
|
static BOOL use_tmodel_delays = FALSE;
|
||||||
|
|
||||||
static BOOL inverters_needed(void)
|
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.
|
/* This function compacts the gen_tab, returning a new PTABLE.
|
||||||
Aliases are transformed and removed as described below.
|
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
|
PTABLE created by the first call. The algorithm here will
|
||||||
only transform one level of aliases.
|
only transform one level of aliases.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1131,7 +1158,7 @@ static void gen_gates(PTABLE gate_tab, SYM_TAB parser_symbols)
|
||||||
tok_count = 0;
|
tok_count = 0;
|
||||||
gate_op = 0;
|
gate_op = 0;
|
||||||
in_count = 0;
|
in_count = 0;
|
||||||
while (val != '\0') {
|
while (val != '\0') { // while val loop
|
||||||
tok_count++;
|
tok_count++;
|
||||||
if (val == LEX_ID) {
|
if (val == LEX_ID) {
|
||||||
idnum++;
|
idnum++;
|
||||||
|
|
@ -1170,13 +1197,33 @@ static void gen_gates(PTABLE gate_tab, SYM_TAB parser_symbols)
|
||||||
goto quick_return;
|
goto quick_return;
|
||||||
}
|
}
|
||||||
val = lexer_scan(lxr);
|
val = lexer_scan(lxr);
|
||||||
}
|
} // end while val loop
|
||||||
|
|
||||||
if (in_count == 1) { // buffer or inverter
|
if (in_count == 1) { // buffer or inverter
|
||||||
if (gate_op != 0) goto quick_return;
|
if (gate_op != 0) goto quick_return;
|
||||||
ds_cat_str(&gate_name, lex_gate_name('~', found_tilde));
|
ds_cat_str(&gate_name, lex_gate_name('~', found_tilde));
|
||||||
} else if (in_count >= 2) { // AND, OR. XOR and inverses
|
} else if (in_count >= 2) { // AND, OR. XOR and inverses
|
||||||
if (gate_op == 0) goto quick_return;
|
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 {
|
} else {
|
||||||
goto quick_return;
|
goto quick_return;
|
||||||
}
|
}
|
||||||
|
|
@ -1537,7 +1584,19 @@ BOOL f_logicexp(char *line)
|
||||||
/* timing model */
|
/* timing model */
|
||||||
t = lex_scan();
|
t = lex_scan();
|
||||||
if (!expect_token(t, LEX_ID, NULL, TRUE, 12)) goto error_return;
|
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,
|
(void) add_sym_tab_entry(parse_lexer->lexer_buf,
|
||||||
SYM_TMODEL, &parse_lexer->lexer_sym_tab);
|
SYM_TMODEL, &parse_lexer->lexer_sym_tab);
|
||||||
ret_val = bparse(line, FALSE);
|
ret_val = bparse(line, FALSE);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
void initialize_udevice(char *subckt_line)
|
||||||
{
|
{
|
||||||
Xlatep xdata;
|
Xlatep xdata;
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,6 @@ void initialize_udevice(char *subckt_line);
|
||||||
struct card *replacement_udevice_cards(void);
|
struct card *replacement_udevice_cards(void);
|
||||||
void cleanup_udevice(void);
|
void cleanup_udevice(void);
|
||||||
void u_add_instance(char *str);
|
void u_add_instance(char *str);
|
||||||
|
void u_add_logicexp_model(char *tmodel, char *xspice_gate, char *model_name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue