1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-26 16:01:31 +02:00

b2/: add test for redundant conditions in hierarchy

This commit is contained in:
Werner Almesberger 2012-05-31 12:33:52 -03:00
parent 2239440ef1
commit 39382b1872
3 changed files with 118 additions and 6 deletions

View File

@ -77,10 +77,26 @@ struct condition *new_condition(enum relop relop, const char *word)
} }
static int comp(const void *a, enum relop op, const void *b, const void *user)
{
return compare(user, a, op, b);
}
static void check_redundant(const struct field *f,
const struct condition *c1, const struct condition *c2)
{
if (relop_implies(c1->relop, c2->relop, &c1->value, &c2->value,
comp, f->fmt))
yywarn("redundant condition");
}
void field_finalize(struct field *field) void field_finalize(struct field *field)
{ {
const struct selector *sel; const struct selector *sel, *s2;
struct condition *cond; struct condition *cond;
const struct condition *c2;
for (sel = field->sel; sel; sel = sel->next) for (sel = field->sel; sel; sel = sel->next)
for (cond = sel->cond; cond; cond = cond->next) for (cond = sel->cond; cond; cond = cond->next)
@ -88,6 +104,14 @@ void field_finalize(struct field *field)
&cond->value)) &cond->value))
yyerrorf("invalid value in selection"); yyerrorf("invalid value in selection");
/* @@@ indicate exact location */ /* @@@ indicate exact location */
for (sel = field->sel; sel; sel = sel->next)
for (cond = sel->cond; cond; cond = cond->next) {
for (c2 = cond->next; c2; c2 = c2->next)
check_redundant(field, cond, c2);
for (s2 = sel->next; s2; s2 = s2->next)
for (c2 = s2->cond; c2; c2 = c2->next)
check_redundant(field, cond, c2);
}
} }

View File

@ -16,6 +16,78 @@
#include "relop.h" #include "relop.h"
/*
* Operator to use for
*
* forall X: (A op B) == ((X opa A) -> (X opb B))
*
* For unlimited sets of values:
*
* opa -> < <= == >= >
* opb
* < >= >= 0 0 0
* <= > >= 0 0 0
* == > >= == <= <
* >= 0 0 0 <= <
* > 0 0 0 <= <=
*
* For limited sets of values, we could decide also in some edge cases,
* but let's save such sophistication for later.
*/
static const enum relop implies_op[idx_n][idx_n] = {
[idx_lt][idx_lt] = rel_ge,
[idx_lt][idx_le] = rel_ge,
[idx_le][idx_lt] = rel_gt,
[idx_le][idx_le] = rel_ge,
[idx_eq][idx_lt] = rel_gt,
[idx_eq][idx_le] = rel_ge,
[idx_eq][idx_eq] = rel_eq,
};
static int relop2index(enum relop op)
{
switch (op) {
case rel_lt:
return idx_lt;
case rel_le:
return idx_le;
case rel_eq:
return idx_eq;
case rel_ge:
return idx_ge;
case rel_gt:
return idx_gt;
default:
abort();
}
}
static enum relop swap_op(enum relop op)
{
return idx_n-1-relop2index(op);
}
int relop_implies(enum relop opa, enum relop opb, const void *a, const void *b,
int (*cmp)(const void *a, enum relop op, const void *b, const void *user),
const void *user)
{
if (opa <= opb)
return cmp(a,
implies_op[relop2index(opa)][relop2index(opb)], b, user);
else
return cmp(b,
swap_op(implies_op[relop2index(opb)][relop2index(opa)]),
a, user);
}
void dump_relop(FILE *file, enum relop op) void dump_relop(FILE *file, enum relop op)
{ {
switch (op) { switch (op) {

View File

@ -16,15 +16,31 @@
#include <stdio.h> #include <stdio.h>
enum relop_idx {
idx_lt = 0,
idx_le = 1,
idx_eq = 2,
idx_ge = 3,
idx_gt = 4,
idx_n = 5
};
enum relop { enum relop {
rel_lt = 1 << 0, rel_lt = 1 << idx_lt,
rel_le = 1 << 1, rel_le = 1 << idx_le,
rel_eq = 1 << 2, rel_eq = 1 << idx_eq,
rel_ge = 1 << 3, rel_ge = 1 << idx_ge,
rel_gt = 1 << 4, rel_gt = 1 << idx_gt,
}; };
/*
* relop_implies checks whether, for all X: (X opb A) -> (X opa B)
*/
int relop_implies(enum relop opa, enum relop opb, const void *a, const void *b,
int (*cmp)(const void *a, enum relop op, const void *b, const void *user),
const void *user);
void dump_relop(FILE *file, enum relop op); void dump_relop(FILE *file, enum relop op);
#endif /* !RELOP_H */ #endif /* !RELOP_H */