V0.8: Fix single bit reductions with 1'bz input.
This patch mirrors what was done in development to support single bit reductions correctly.
This commit is contained in:
parent
ddf68ca14c
commit
f112b77d3b
17
eval_tree.cc
17
eval_tree.cc
|
|
@ -1483,6 +1483,7 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
|
||||
verinum val = rval->value();
|
||||
verinum::V res;
|
||||
bool invert = false;
|
||||
|
||||
switch (op_) {
|
||||
|
||||
|
|
@ -1511,6 +1512,8 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
break;
|
||||
}
|
||||
|
||||
case 'A':
|
||||
invert = true;
|
||||
case '&': {
|
||||
res = verinum::V1;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
|
|
@ -1518,6 +1521,8 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
break;
|
||||
}
|
||||
|
||||
case 'N':
|
||||
invert = true;
|
||||
case '|': {
|
||||
res = verinum::V0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
|
|
@ -1525,6 +1530,8 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
break;
|
||||
}
|
||||
|
||||
case 'X':
|
||||
invert = true;
|
||||
case '^': {
|
||||
/* Reduction XOR. */
|
||||
unsigned ones = 0, unknown = 0;
|
||||
|
|
@ -1540,17 +1547,17 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
break;
|
||||
}
|
||||
|
||||
if (unknown)
|
||||
return new NetEConst(verinum(verinum::Vx,1,true));
|
||||
if (ones%2)
|
||||
return new NetEConst(verinum(verinum::V1,1,true));
|
||||
return new NetEConst(verinum(verinum::V0,1,true));
|
||||
if (unknown) res = verinum::Vx;
|
||||
else if (ones%2) res = verinum::V1;
|
||||
else res = verinum::V0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (invert) res = ~res;
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2012,6 +2012,11 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
|||
} else if (inv) {
|
||||
assert(res.base >= 4);
|
||||
fprintf(vvp_out, " %%inv %u, 1;\n", res.base);
|
||||
} else {
|
||||
/* We need to convert a 1'bz to 1'bx. */
|
||||
assert(res.base >= 4);
|
||||
fprintf(vvp_out, " %%inv %u, 1;\n", res.base);
|
||||
fprintf(vvp_out, " %%inv %u, 1;\n", res.base);
|
||||
}
|
||||
|
||||
/* If the result needs to be bigger then the calculated
|
||||
|
|
|
|||
12
verinum.cc
12
verinum.cc
|
|
@ -956,6 +956,18 @@ verinum concat(const verinum&left, const verinum&right)
|
|||
return res;
|
||||
}
|
||||
|
||||
verinum::V operator ~ (verinum::V l)
|
||||
{
|
||||
switch(l) {
|
||||
case verinum::V0:
|
||||
return verinum::V1;
|
||||
case verinum::V1:
|
||||
return verinum::V0;
|
||||
default:
|
||||
return verinum::Vx;
|
||||
}
|
||||
}
|
||||
|
||||
verinum::V operator | (verinum::V l, verinum::V r)
|
||||
{
|
||||
if (l == verinum::V1)
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ extern verinum trim_vnum(const verinum&);
|
|||
extern std::ostream& operator<< (std::ostream&, const verinum&);
|
||||
extern std::ostream& operator<< (std::ostream&, verinum::V);
|
||||
|
||||
extern verinum::V operator ~ (verinum::V l);
|
||||
extern verinum::V operator | (verinum::V l, verinum::V r);
|
||||
extern verinum::V operator & (verinum::V l, verinum::V r);
|
||||
extern verinum::V operator ^ (verinum::V l, verinum::V r);
|
||||
|
|
|
|||
Loading…
Reference in New Issue