diff --git a/PExpr.cc b/PExpr.cc index dbaed82db..3db0af799 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -73,6 +73,16 @@ PEBComp::~PEBComp() { } +PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r) +: PEBinary(op, l, r) +{ + assert(op == 'a' || op == 'o'); +} + +PEBLogic::~PEBLogic() +{ +} + PEBShift::PEBShift(char op, PExpr*l, PExpr*r) : PEBinary(op, l, r) { diff --git a/PExpr.h b/PExpr.h index 348a6a912..a7d2b54db 100644 --- a/PExpr.h +++ b/PExpr.h @@ -497,6 +497,25 @@ class PEBComp : public PEBinary { NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const; }; +/* + * This derived class is for handling logical expressions: && and ||. +*/ +class PEBLogic : public PEBinary { + + public: + explicit PEBLogic(char op, PExpr*l, PExpr*r); + ~PEBLogic(); + + virtual unsigned test_width(Design*des, NetScope*scope, + unsigned min, unsigned lval, + ivl_variable_type_t&expr_type, + bool&flag); + + NetExpr* elaborate_expr(Design*des, NetScope*scope, + int expr_width, bool sys_task_arg) const; + NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const; +}; + class PEBShift : public PEBinary { public: diff --git a/elab_expr.cc b/elab_expr.cc index ee097d2d1..3ea8ce605 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -294,11 +294,12 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des, case 'a': case 'o': - lp = condition_reduce(lp); - rp = condition_reduce(rp); - tmp = new NetEBLogic(op_, lp, rp); - tmp->set_line(*this); - break; + cerr << get_fileline() << ": internal error: " + << "Elaboration of " << human_readable_op(op_) + << " Should have been handled in NetEBLogic::elaborate." + << endl; + des->errors += 1; + return 0; case 'p': tmp = new NetEBPow(op_, lp, rp); @@ -799,6 +800,54 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope, return tmp; } +unsigned PEBLogic::test_width(Design*des, NetScope*scope, + unsigned min, unsigned lval, + ivl_variable_type_t&expr_type_out, + bool&unsized_flag) +{ + expr_type_ = IVL_VT_LOGIC; + expr_width_ = 1; + expr_type_out = expr_type_; + return expr_width_; +} + +NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope, + int expr_width_dummp, bool sys_task_arg) const +{ + assert(left_); + assert(right_); + + // The left and right expressions are self-determined and + // independent. Run their test_width methods independently. We + // don't need the widths here, but we do need the expressions + // to calculate their self-determined width and type. + + bool left_flag = false; + ivl_variable_type_t left_type = IVL_VT_NO_TYPE; + left_->test_width(des, scope, 0, 0, left_type, left_flag); + + bool right_flag = false; + ivl_variable_type_t right_type = IVL_VT_NO_TYPE; + right_->test_width(des, scope, 0, 0, right_type, right_flag); + + NetExpr*lp = elab_and_eval(des, scope, left_, -1); + NetExpr*rp = elab_and_eval(des, scope, right_, -1); + if ((lp == 0) || (rp == 0)) { + delete lp; + delete rp; + return 0; + } + + lp = condition_reduce(lp); + rp = condition_reduce(rp); + + NetEBLogic*tmp = new NetEBLogic(op_, lp, rp); + tmp->set_line(*this); + tmp->set_width(1); + + return tmp; +} + unsigned PEBShift::test_width(Design*des, NetScope*scope, unsigned min, unsigned lval, ivl_variable_type_t&expr_type__, diff --git a/elab_pexpr.cc b/elab_pexpr.cc index c249ff718..a8728cafc 100644 --- a/elab_pexpr.cc +++ b/elab_pexpr.cc @@ -81,6 +81,28 @@ NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const return tmp; } +NetExpr*PEBLogic::elaborate_pexpr(Design*des, NetScope*scope) const +{ + NetExpr*lp = left_->elaborate_pexpr(des, scope); + NetExpr*rp = right_->elaborate_pexpr(des, scope); + if ((lp == 0) || (rp == 0)) { + delete lp; + delete rp; + return 0; + } + + NetEBLogic*tmp = new NetEBLogic(op_, lp, rp); + tmp->set_line(*this); + bool flag = tmp->set_width(1); + if (flag == false) { + cerr << get_fileline() << ": internal error: " + "expression bit width of comparison != 1." << endl; + des->errors += 1; + } + + return tmp; +} + /* * Event though parameters are not generally sized, parameter * expressions can include concatenation expressions. This requires diff --git a/netlist.h b/netlist.h index 9bcb01272..a73c68b98 100644 --- a/netlist.h +++ b/netlist.h @@ -3270,7 +3270,7 @@ class NetEBLogic : public NetEBinary { NetEBLogic(char op, NetExpr*l, NetExpr*r); ~NetEBLogic(); - virtual bool set_width(unsigned w, bool last_chance); + virtual bool set_width(unsigned w, bool last_chance =false); virtual NetEBLogic* dup_expr() const; virtual NetEConst* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*, NetScope*scope); diff --git a/parse.y b/parse.y index 0f9d6bbce..a860fdcce 100644 --- a/parse.y +++ b/parse.y @@ -1034,12 +1034,12 @@ expression $$ = tmp; } | expression K_LOR expression - { PEBinary*tmp = new PEBinary('o', $1, $3); + { PEBinary*tmp = new PEBLogic('o', $1, $3); FILE_NAME(tmp, @2); $$ = tmp; } | expression K_LAND expression - { PEBinary*tmp = new PEBinary('a', $1, $3); + { PEBinary*tmp = new PEBLogic('a', $1, $3); FILE_NAME(tmp, @2); $$ = tmp; }