Add optional debug code to check for name collisions. Connector nodes between gates now have a con_ prefix.
This commit is contained in:
parent
5b3862ebc7
commit
6a067378cb
|
|
@ -189,6 +189,79 @@ struct timing_data {
|
|||
int estimate;
|
||||
};
|
||||
|
||||
/* btree */
|
||||
typedef struct nnode *TREE;
|
||||
struct nnode {
|
||||
char *name;
|
||||
TREE left;
|
||||
TREE right;
|
||||
};
|
||||
|
||||
static TREE btree_root = NULL;
|
||||
|
||||
/* #define UDEV_BTREE */
|
||||
#ifdef UDEV_BTREE
|
||||
static TREE new_nnode(char *name)
|
||||
{
|
||||
TREE newp;
|
||||
newp = TMALLOC(struct nnode, 1);
|
||||
newp->left = NULL;
|
||||
newp->right = NULL;
|
||||
newp->name = TMALLOC(char, strlen(name) + 1);
|
||||
strcpy(newp->name, name);
|
||||
return newp;
|
||||
}
|
||||
|
||||
TREE tinsert(char *name, TREE t)
|
||||
{
|
||||
int cmp;
|
||||
if (t == NULL) {
|
||||
t = new_nnode(name);
|
||||
return t;
|
||||
}
|
||||
cmp = strcmp(name, t->name);
|
||||
if (cmp < 0) {
|
||||
t->left = tinsert(name, t->left);
|
||||
} else if (cmp > 0) {
|
||||
t->right = tinsert(name, t->right);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
int tmember(char *name, TREE t)
|
||||
{
|
||||
int cmp;
|
||||
while (t != NULL) {
|
||||
cmp = strcmp(name, t->name);
|
||||
if (cmp == 0) {
|
||||
return 1;
|
||||
} else if (cmp < 0) {
|
||||
t = t->left;
|
||||
} else {
|
||||
t = t->right;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void delete_btree(TREE t)
|
||||
{
|
||||
if (t == NULL) { return; }
|
||||
delete_btree(t->left);
|
||||
delete_btree(t->right);
|
||||
tfree(t->name);
|
||||
tfree(t);
|
||||
}
|
||||
|
||||
void print_btree(TREE t)
|
||||
{
|
||||
if (t == NULL) { return; }
|
||||
print_btree(t->left);
|
||||
printf("%s\n", t->name);
|
||||
print_btree(t->right);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* NOTE
|
||||
Pin lists contain the names of instance inputs, outputs, tristate outputs.
|
||||
These pin_lists are created by add_..._pin() calls within the various
|
||||
|
|
@ -215,10 +288,47 @@ static int pins_and_ports = 0; // If non-zero then generate pins and ports
|
|||
static struct pin_entry *subckt_ports = NULL;
|
||||
static struct pin_entry *input_pins = NULL;
|
||||
static struct pin_entry *output_pins = NULL;
|
||||
static struct pin_entry *tristate_pins = NULL;
|
||||
static struct pin_entry *tristate_pins = NULL; // Subset of output pins
|
||||
/* .model d_zero_inv99 d_inverter just once per subckt */
|
||||
static BOOL add_zero_delay_inverter_model = FALSE;
|
||||
|
||||
static void check_name_unused(char *name)
|
||||
{
|
||||
if (!pins_and_ports) { return; }
|
||||
#ifdef UDEV_BTREE
|
||||
if (tmember(name, btree_root)) {
|
||||
printf("ERROR udevice name %s already used\n", name);
|
||||
return;
|
||||
} else {
|
||||
btree_root = tinsert(name, btree_root);
|
||||
}
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UDEV_BTREE
|
||||
static void check_for_name_collisions(void)
|
||||
{
|
||||
struct pin_entry *pin;
|
||||
for (pin = subckt_ports; pin; pin = pin->next) {
|
||||
if (tmember(pin->name, btree_root)) {
|
||||
printf("ERROR subckt port name collision %s\n", pin->name);
|
||||
}
|
||||
}
|
||||
for (pin = input_pins; pin; pin = pin->next) {
|
||||
if (tmember(pin->name, btree_root)) {
|
||||
printf("ERROR input pin name collision %s\n", pin->name);
|
||||
}
|
||||
}
|
||||
for (pin = output_pins; pin; pin = pin->next) {
|
||||
if (tmember(pin->name, btree_root)) {
|
||||
printf("ERROR output pin name collision %s\n", pin->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pin_entry *add_pin(char *name, int pin_type, BOOL is_port)
|
||||
{
|
||||
struct pin_entry **plist = NULL, *x = NULL, *last = NULL;
|
||||
|
|
@ -885,11 +995,18 @@ void initialize_udevice(char *subckt_line)
|
|||
}
|
||||
/* reset for the new subckt */
|
||||
add_zero_delay_inverter_model = FALSE;
|
||||
#ifdef UDEV_BTREE
|
||||
delete_btree(btree_root);
|
||||
#endif
|
||||
btree_root = NULL;
|
||||
}
|
||||
|
||||
void cleanup_udevice(void)
|
||||
{
|
||||
create_ports_list();
|
||||
#ifdef UDEV_BTREE
|
||||
check_for_name_collisions();
|
||||
#endif
|
||||
cleanup_translated_xlator();
|
||||
delete_xlator(model_xlatorp);
|
||||
model_xlatorp = NULL;
|
||||
|
|
@ -901,6 +1018,12 @@ void cleanup_udevice(void)
|
|||
subckt_saved = NULL;
|
||||
}
|
||||
add_zero_delay_inverter_model = FALSE;
|
||||
#ifdef UDEV_BTREE
|
||||
printf("btree-->\n");
|
||||
print_btree(btree_root);
|
||||
delete_btree(btree_root);
|
||||
#endif
|
||||
btree_root = NULL;
|
||||
}
|
||||
|
||||
static Xlatep create_xlate_model(char *delays,
|
||||
|
|
@ -1445,16 +1568,22 @@ char *new_inverter(char *iname, char *node, Xlatorp xlp)
|
|||
{
|
||||
/* Return the name of the output of the new inverter */
|
||||
/* tfree the returned string after it has been used by the caller */
|
||||
char *tmp = NULL;
|
||||
char *tmp = NULL, *instance_name = NULL, *not_node = NULL;
|
||||
Xlatep xdata = NULL;
|
||||
|
||||
tmp = tprintf("a%s_%s %s not_a%s_%s d_zero_inv99",
|
||||
iname, node, node, iname, node);
|
||||
instance_name = tprintf("a%s_%s", iname, node);
|
||||
check_name_unused(instance_name);
|
||||
not_node = tprintf("not_%s", instance_name);
|
||||
check_name_unused(not_node);
|
||||
tmp = tprintf("%s %s %s d_zero_inv99",
|
||||
instance_name, node, not_node);
|
||||
/* instantiate the new inverter */
|
||||
/* e.g. au5_s1bar s1bar not_au5_s1bar d_zero_inv99 */
|
||||
xdata = create_xlate_translated(tmp);
|
||||
(void) add_xlator(xlp, xdata);
|
||||
tfree(tmp);
|
||||
tfree(instance_name);
|
||||
tfree(not_node);
|
||||
/* the name of the inverter output */
|
||||
tmp = tprintf("not_a%s_%s", iname, node);
|
||||
return tmp;
|
||||
|
|
@ -1543,7 +1672,9 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip)
|
|||
tmodel = ip->tmodel;
|
||||
/* model name, same for each dff */
|
||||
modelnm = tprintf("d_a%s_%s", iname, itype);
|
||||
check_name_unused(modelnm);
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
char *instance_name = NULL;
|
||||
qout = qarr[i];
|
||||
add_output_pin(qout);
|
||||
if (eq(qout, "$d_nc")) {
|
||||
|
|
@ -1554,13 +1685,16 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip)
|
|||
if (eq(qbout, "$d_nc")) {
|
||||
qbout = "NULL";
|
||||
}
|
||||
instance_name = tprintf("a%s_%d", iname, i);
|
||||
check_name_unused(instance_name);
|
||||
add_input_pin(darr[i]);
|
||||
s1 = tprintf( "a%s_%d %s %s %s %s %s %s %s",
|
||||
iname, i, darr[i], clk, preb, clrb, qout, qbout, modelnm
|
||||
s1 = tprintf( "%s %s %s %s %s %s %s %s",
|
||||
instance_name, darr[i], clk, preb, clrb, qout, qbout, modelnm
|
||||
);
|
||||
xdata = create_xlate_instance(s1, " d_dff", tmodel, modelnm);
|
||||
xxp = add_xlator(xxp, xdata);
|
||||
tfree(s1);
|
||||
tfree(instance_name);
|
||||
}
|
||||
if (!gen_timing_model(tmodel, "ueff", "d_dff", modelnm, xxp)) {
|
||||
printf("WARNING unable to find tmodel %s for %s d_dff\n",
|
||||
|
|
@ -1622,7 +1756,9 @@ static Xlatorp gen_jkff_instance(struct jkff_instance *ip)
|
|||
tmodel = ip->tmodel;
|
||||
/* model name, same for each jkff */
|
||||
modelnm = tprintf("d_a%s_%s", iname, itype);
|
||||
check_name_unused(modelnm);
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
char *instance_name = NULL;
|
||||
qout = qarr[i];
|
||||
add_output_pin(qout);
|
||||
if (eq(qout, "$d_nc")) {
|
||||
|
|
@ -1635,12 +1771,16 @@ static Xlatorp gen_jkff_instance(struct jkff_instance *ip)
|
|||
}
|
||||
add_input_pin(jarr[i]);
|
||||
add_input_pin(karr[i]);
|
||||
s1 = tprintf("a%s_%d %s %s %s %s %s %s %s %s",
|
||||
iname, i, jarr[i], karr[i], clkb, preb, clrb, qout, qbout, modelnm
|
||||
instance_name = tprintf("a%s_%d", iname, i);
|
||||
check_name_unused(instance_name);
|
||||
s1 = tprintf("%s %s %s %s %s %s %s %s %s",
|
||||
instance_name, jarr[i], karr[i], clkb, preb, clrb,
|
||||
qout, qbout, modelnm
|
||||
);
|
||||
xdata = create_xlate_instance(s1, " d_jkff", tmodel, modelnm);
|
||||
xxp = add_xlator(xxp, xdata);
|
||||
tfree(s1);
|
||||
tfree(instance_name);
|
||||
}
|
||||
if (!gen_timing_model(tmodel, "ueff", "d_jkff", modelnm, xxp)) {
|
||||
printf("WARNING unable to find tmodel %s for %s d_jkff\n",
|
||||
|
|
@ -1696,16 +1836,20 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
|
|||
tmodel = ip->tmodel;
|
||||
/* model name, same for each latch */
|
||||
modelnm = tprintf("d_a%s_%s", iname, itype);
|
||||
check_name_unused(modelnm);
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
char *instance_name = NULL;
|
||||
qout = qarr[i];
|
||||
add_output_pin(qout);
|
||||
instance_name = tprintf("a%s_%d", iname, i);
|
||||
check_name_unused(instance_name);
|
||||
if (eq(qout, "$d_nc")) {
|
||||
/* NULL not allowed??? */
|
||||
s1 = tprintf("a%s_%d %s %s %s %s nco%s_%d",
|
||||
iname, i, darr[i], gate, preb, clrb, iname, i);
|
||||
s1 = tprintf("%s %s %s %s %s nco%s_%d",
|
||||
instance_name, darr[i], gate, preb, clrb, iname, i);
|
||||
} else {
|
||||
s1 = tprintf("a%s_%d %s %s %s %s %s",
|
||||
iname, i, darr[i], gate, preb, clrb, qout);
|
||||
s1 = tprintf("%s %s %s %s %s %s",
|
||||
instance_name, darr[i], gate, preb, clrb, qout);
|
||||
}
|
||||
add_input_pin(darr[i]);
|
||||
qbout = qbarr[i];
|
||||
|
|
@ -1722,6 +1866,7 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip)
|
|||
tfree(s1);
|
||||
tfree(s2);
|
||||
tfree(s3);
|
||||
tfree(instance_name);
|
||||
}
|
||||
if (!gen_timing_model(tmodel, "ugff", "d_dlatch", modelnm, xxp)) {
|
||||
printf("WARNING unable to find tmodel %s for %s d_dlatch\n",
|
||||
|
|
@ -1745,7 +1890,7 @@ static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
|||
int num_ins_kept = 0;
|
||||
char *model_name = NULL, *inst = NULL, **connector = NULL;
|
||||
char *new_inst = NULL, *model_stmt = NULL, *final_model_name = NULL;
|
||||
char *new_stmt = NULL;
|
||||
char *new_stmt = NULL, *instance_name = NULL;
|
||||
char *tmp;
|
||||
size_t sz = 0;
|
||||
Xlatorp xxp = NULL;
|
||||
|
|
@ -1779,6 +1924,7 @@ static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
|||
output = compi->output;
|
||||
tmodel = compi->tmodel;
|
||||
model_name = tprintf("d_%s_%s", inst, itype);
|
||||
check_name_unused(model_name);
|
||||
connector = TMALLOC(char *, num_gates);
|
||||
xxp = create_xlator();
|
||||
k = 0;
|
||||
|
|
@ -1793,6 +1939,7 @@ static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
|||
k = 0;
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
connector[i] = tprintf("con_%s_%d", inst, i);
|
||||
check_name_unused(connector[i]);
|
||||
num_ins_kept = 0;
|
||||
tmp[0] = '\0';
|
||||
/* $d_hi AND gate inputs are ignored */
|
||||
|
|
@ -1806,11 +1953,14 @@ static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
|||
k++;
|
||||
}
|
||||
if (num_ins_kept >= 2) {
|
||||
new_inst = tprintf("a%s_%d [%s ] %s %s", inst, i,
|
||||
instance_name = tprintf("a%s_%d", inst, i);
|
||||
check_name_unused(instance_name);
|
||||
new_inst = tprintf("%s [%s ] %s %s", instance_name,
|
||||
tmp, connector[i], model_name);
|
||||
xdata = create_xlate_translated(new_inst);
|
||||
xxp = add_xlator(xxp, xdata);
|
||||
tfree(new_inst);
|
||||
tfree(instance_name);
|
||||
} else if (num_ins_kept == 1) {
|
||||
/*
|
||||
connector[i] is the remaining input connected
|
||||
|
|
@ -1818,6 +1968,7 @@ static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
|||
*/
|
||||
tfree(connector[i]);
|
||||
connector[i] = tprintf("%s", tmp);
|
||||
check_name_unused(connector[i]);
|
||||
}
|
||||
}
|
||||
/* .model statement for the input gates */
|
||||
|
|
@ -1828,6 +1979,7 @@ static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
|||
|
||||
/* Final OR/NOR, AND/NAND gate */
|
||||
final_model_name = tprintf("%s_out", model_name);
|
||||
check_name_unused(final_model_name);
|
||||
tfree(tmp);
|
||||
|
||||
sz = 0;
|
||||
|
|
@ -1840,12 +1992,15 @@ static Xlatorp gen_compound_instance(struct compound_instance *compi)
|
|||
sprintf(tmp + strlen(tmp), " %s", connector[i]);
|
||||
}
|
||||
/* instance statement for the final gate */
|
||||
new_stmt = tprintf("a%s_out [%s ] %s %s",
|
||||
inst, tmp, output, final_model_name);
|
||||
instance_name = tprintf("a%s_out", inst);
|
||||
check_name_unused(instance_name);
|
||||
new_stmt = tprintf("%s [%s ] %s %s",
|
||||
instance_name, tmp, output, final_model_name);
|
||||
add_output_pin(output);
|
||||
xdata = create_xlate_translated(new_stmt);
|
||||
xxp = add_xlator(xxp, xdata);
|
||||
tfree(new_stmt);
|
||||
tfree(instance_name);
|
||||
tfree(tmp);
|
||||
/* timing model for output gate */
|
||||
if (!gen_timing_model(tmodel, "ugate", outgate,
|
||||
|
|
@ -1871,7 +2026,7 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
BOOL tristate_array = FALSE, simple_array = FALSE;
|
||||
BOOL add_tristate = FALSE;
|
||||
char *modelnm = NULL, *startvec = NULL, *endvec = NULL;
|
||||
char *input_buf = NULL;
|
||||
char *input_buf = NULL, *instance_name = NULL;
|
||||
int i, j, k, width, num_gates, num_ins, num_outs;
|
||||
size_t sz;
|
||||
Xlatorp xxp = NULL;
|
||||
|
|
@ -1939,6 +2094,9 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
sprintf(input_buf + strlen(input_buf), " %s", inarr[i]);
|
||||
}
|
||||
/* instance name and inputs */
|
||||
instance_name = tprintf("a%s", iname);
|
||||
check_name_unused(instance_name);
|
||||
tfree(instance_name);
|
||||
/* add the tristate enable if required on original */
|
||||
if (enable) {
|
||||
if (!add_tristate) {
|
||||
|
|
@ -1958,10 +2116,11 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
tfree(input_buf);
|
||||
|
||||
/* connector if required for tristate */
|
||||
connector = tprintf("a%s_%s", iname, outarr[0]);
|
||||
connector = tprintf("con_a%s_%s", iname, outarr[0]);
|
||||
|
||||
/* keep a copy of the model name of original gate */
|
||||
modelnm = tprintf("d_a%s_%s", iname, itype);
|
||||
check_name_unused(modelnm);
|
||||
|
||||
if (!add_tristate) {
|
||||
char *instance_stmt = NULL;
|
||||
|
|
@ -1995,6 +2154,7 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
Complete the translation of the original gate adding
|
||||
the connector as output + model name.
|
||||
*/
|
||||
check_name_unused(connector);
|
||||
new_stmt = tprintf("%s %s %s", inst_begin, connector, modelnm);
|
||||
xdata = create_xlate_instance(new_stmt, xspice, "", modelnm);
|
||||
xxp = add_xlator(xxp, xdata);
|
||||
|
|
@ -2007,6 +2167,7 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
/* now the added tristate */
|
||||
/* model name of added tristate */
|
||||
new_model_nm = tprintf("d_a%s_tribuf", iname);
|
||||
check_name_unused(new_model_nm);
|
||||
new_stmt = tprintf("a%s_tri %s %s %s %s",
|
||||
iname, connector, enable, outarr[0], new_model_nm);
|
||||
xdata = create_xlate_instance(new_stmt, "d_tristate",
|
||||
|
|
@ -2055,6 +2216,7 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
}
|
||||
/* model name, same for all primary gates */
|
||||
primary_model = tprintf("d_a%s_%s", iname, itype);
|
||||
check_name_unused(primary_model);
|
||||
for (i = 0; i < num_gates; i++) {
|
||||
/* inputs */
|
||||
/* First calculate the space */
|
||||
|
|
@ -2075,6 +2237,9 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
k++;
|
||||
}
|
||||
/* create new instance name for primary gate */
|
||||
instance_name = tprintf("a%s_%d", iname, i);
|
||||
check_name_unused(instance_name);
|
||||
tfree(instance_name);
|
||||
if (enable) {
|
||||
if (!add_tristate) {
|
||||
s1 = tprintf("a%s_%d %s%s%s %s",
|
||||
|
|
@ -2083,7 +2248,8 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
s1 = tprintf("a%s_%d %s%s%s",
|
||||
iname, i, startvec, input_buf, endvec);
|
||||
/* connector if required for tristate */
|
||||
connector = tprintf("a%s_%d_%s", iname, i, outarr[i]);
|
||||
connector = tprintf("con_a%s_%d_%s", iname, i, outarr[i]);
|
||||
check_name_unused(connector);
|
||||
}
|
||||
} else {
|
||||
s1 = tprintf("a%s_%d %s%s%s",
|
||||
|
|
@ -2138,16 +2304,21 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip)
|
|||
}
|
||||
/* model name of added tristate */
|
||||
modelnm = tprintf("d_a%s_tribuf", iname);
|
||||
if (i == 0) {
|
||||
check_name_unused(modelnm);
|
||||
}
|
||||
/*
|
||||
instance name of added tristate, connector,
|
||||
enable, original primary gate output, timing model.
|
||||
*/
|
||||
s1 = tprintf("a%s_%d_tri %s %s %s %s", iname, i, connector,
|
||||
instance_name = tprintf("a%s_%d_tri", iname, i);
|
||||
s1 = tprintf("%s %s %s %s %s", instance_name, connector,
|
||||
enable, outarr[i], modelnm);
|
||||
xdata = create_xlate_instance(s1, "d_tristate",
|
||||
tmodel, modelnm);
|
||||
xxp = add_xlator(xxp, xdata);
|
||||
tfree(s1);
|
||||
tfree(instance_name);
|
||||
if (i == 0 && !gen_timing_model(tmodel, "utgate",
|
||||
"d_tristate", modelnm, xxp)) {
|
||||
printf("WARNING unable to find tmodel %s for %s %s\n",
|
||||
|
|
|
|||
Loading…
Reference in New Issue