From 225fcf6bf0ca0b6b3df87849d8ac616bdf8c30ab Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 25 Mar 2008 19:00:00 -0700 Subject: [PATCH] Pad CA bit arguments and make reductions and ! self-determined. Binary bit based operators were not padding arguments if they had different widths. The reduction operators and ! were not correctly evaluating their arguments in a self-determined context. --- elab_expr.cc | 18 ++++++++++++++---- elab_net.cc | 7 +++---- expr_synth.cc | 31 ++++++++++++------------------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 91d2a9a2a..50b51feaf 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1743,13 +1743,23 @@ NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope, NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, int expr_wid, bool) const { + /* Reduction operators and ! always have a self determined width. */ + switch (op_) { + case '!': + case '&': // Reduction AND + case '|': // Reduction OR + case '^': // Reduction XOR + case 'A': // Reduction NAND (~&) + case 'N': // Reduction NOR (~|) + case 'X': // Reduction NXOR (~^) + expr_wid = -1; + default: + break; + } + NetExpr*ip = expr_->elaborate_expr(des, scope, expr_wid, false); if (ip == 0) return 0; - /* Should we evaluate expressions ahead of time, - * just like in PEBinary::elaborate_expr() ? - */ - NetExpr*tmp; switch (op_) { default: diff --git a/elab_net.cc b/elab_net.cc index ab3b40334..5ad49436a 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -3125,10 +3125,6 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, Link::strength_t drive0, Link::strength_t drive1) const { - NetExpr*expr = elab_and_eval(des, scope, expr_, width); - if (expr == 0) - return 0; - // Some unary operands allow the operand to be // self-determined, and some do not. unsigned owidth = 0; @@ -3139,6 +3135,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, break; } + NetExpr*expr = elab_and_eval(des, scope, expr_, owidth); + if (expr == 0) return 0; + NetNet* sig = 0; NetLogic*gate; diff --git a/expr_synth.cc b/expr_synth.cc index 046a7acd1..0c0ed80e4 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -157,46 +157,39 @@ NetNet* NetEBBits::synthesize(Design*des) NetScope*scope = lsig->scope(); assert(scope); - if (lsig->vector_width() != rsig->vector_width()) { - cerr << get_fileline() << ": internal error: bitwise (" << op_ - << ") widths do not match: " << lsig->vector_width() - << " != " << rsig->vector_width() << endl; - cerr << get_fileline() << ": : width=" - << lsig->vector_width() << ": " << *left_ << endl; - cerr << get_fileline() << ": : width=" - << rsig->vector_width() << ": " << *right_ << endl; - des->errors += 1; - return 0; - } + unsigned width = lsig->vector_width(); + if (rsig->vector_width() > width) width = rsig->vector_width(); + + lsig = pad_to_width(des, lsig, width); + rsig = pad_to_width(des, rsig, width); assert(lsig->vector_width() == rsig->vector_width()); NetNet*osig = new NetNet(scope, scope->local_symbol(), - NetNet::IMPLICIT, lsig->vector_width()); + NetNet::IMPLICIT, width); osig->local_flag(true); osig->data_type(expr_type()); perm_string oname = scope->local_symbol(); - unsigned wid = lsig->vector_width(); NetLogic*gate; switch (op()) { case '&': - gate = new NetLogic(scope, oname, 3, NetLogic::AND, wid); + gate = new NetLogic(scope, oname, 3, NetLogic::AND, width); break; case 'A': - gate = new NetLogic(scope, oname, 3, NetLogic::NAND, wid); + gate = new NetLogic(scope, oname, 3, NetLogic::NAND, width); break; case '|': - gate = new NetLogic(scope, oname, 3, NetLogic::OR, wid); + gate = new NetLogic(scope, oname, 3, NetLogic::OR, width); break; case '^': - gate = new NetLogic(scope, oname, 3, NetLogic::XOR, wid); + gate = new NetLogic(scope, oname, 3, NetLogic::XOR, width); break; case 'O': - gate = new NetLogic(scope, oname, 3, NetLogic::NOR, wid); + gate = new NetLogic(scope, oname, 3, NetLogic::NOR, width); break; case 'X': - gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, wid); + gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, width); break; default: assert(0);