diff --git a/elab_expr.cc b/elab_expr.cc index 009edd6fa..ec2bc5643 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3634,20 +3634,15 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, << "vector slice." << endl; des->errors += 1; return 0; - } else if (t == IVL_VT_REAL) { - /* - * TODO: Need to modify draw_unary_real() to support - * operations on real variables - */ - cerr << get_fileline() << ": sorry: " - << human_readable_op(op_, true) - << " operation is not yet supported on " - << "reals." << endl; - des->errors += 1; - return 0; - } else if (t == IVL_VT_LOGIC || t == IVL_VT_BOOL) { - if (dynamic_cast (ip)) { - /* invalid operand: operand is a constant number */ + } else if (t == IVL_VT_LOGIC || t == IVL_VT_BOOL || + t == IVL_VT_REAL) { + + if (dynamic_cast (ip) || + dynamic_cast (ip)) { + /* + * invalid operand: operand is a constant + * or real number + */ cerr << get_fileline() << ": error: " << "inappropriate use of " << human_readable_op(op_, true) @@ -3656,6 +3651,12 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, return 0; } + /* + * **** Valid use of operator *** + * For REAL variables draw_unary_real() is ivoked during + * evaluation and for LOGIC/BOOLEAN draw_unary_expr() + * is called for evaluation. + */ tmp = new NetEUnary(op_, ip, expr_wid, signed_flag_); tmp->set_line(*this); } else { diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index f5f9dfe59..933210da8 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -25,6 +25,7 @@ # include # include # include +# include static unsigned long word_alloc_mask = 0x0f; @@ -442,6 +443,84 @@ static int draw_ternary_real(ivl_expr_t expr) return res; } +static int increment(ivl_expr_t e, int s, bool pre) +{ + ivl_signal_t sig; + int r; + int one; + + sig = ivl_expr_signal(e); + r = s; + + /* create a temporary word to hold value 1.0 */ + one = allocate_word(); + fprintf(vvp_out, " %%loadi/wr %d, 1, 0x1000; load 1.0\n", one); + + if (!pre) { + /* + * post-increment must return the non-incremented value. + * Therefore, copy the current value in a new word and return + * it. + */ + r = allocate_word(); + fprintf(vvp_out, " %%mov/wr %d, %d;\n", r, s); + } + + fprintf(vvp_out, " %%add/wr %d, %d;\n", s, one); + fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", sig, s); + + return r; +} + +static inline int pre_increment(ivl_expr_t e, int s) +{ + return increment(e, s, true); +} + +static inline int post_increment(ivl_expr_t e, int s) +{ + return increment(e, s, false); +} + +static int decrement(ivl_expr_t e, int s, bool pre) +{ + ivl_signal_t sig; + int r; + int one; + + sig = ivl_expr_signal(e); + r = s; + + /* create a temporary word to hold value 1.0 */ + one = allocate_word(); + fprintf(vvp_out, " %%loadi/wr %d, 1, 0x1000; load 1.0\n", one); + + if (!pre) { + /* + * post-decrement must return the non-incremented value. + * Therefore, copy the current value in a new word and return + * it. + */ + r = allocate_word(); + fprintf(vvp_out, " %%mov/wr %d, %d;\n", r, s); + } + + fprintf(vvp_out, " %%sub/wr %d, %d;\n", s, one); + fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", sig, s); + + return r; +} + +static inline int pre_decrement(ivl_expr_t e, int s) +{ + return decrement(e, s, true); +} + +static inline int post_decrement(ivl_expr_t e, int s) +{ + return decrement(e, s, false); +} + static int draw_unary_real(ivl_expr_t expr) { ivl_expr_t sube; @@ -494,6 +573,20 @@ static int draw_unary_real(ivl_expr_t expr) assert(0); } + switch (ivl_expr_opcode(expr)) { + case 'I': + return pre_increment(sube, sub); + + case 'i': + return post_increment(sube, sub); + + case 'D': + return pre_decrement(sube, sub); + + case 'd': + return post_decrement(sube, sub); + } + fprintf(stderr, "vvp.tgt error: unhandled real unary operator: %c.\n", ivl_expr_opcode(expr)); assert(0);