diff --git a/design_dump.cc b/design_dump.cc index 471ca32f3..3ebeaae5f 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -824,7 +824,10 @@ void NetAssign::dump(ostream&o, unsigned ind) const o << setw(ind) << ""; dump_lval(o); - o << " = "; + if (op_) + o << " " << op_ << "= "; + else + o << " = "; if (const NetExpr*de = get_delay()) o << "#(" << *de << ") "; diff --git a/elaborate.cc b/elaborate.cc index 8f020bae4..ed85ab6b2 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2271,7 +2271,7 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); if (rv == 0) return 0; - NetAssign*cur = new NetAssign(lv, rv); + NetAssign*cur = new NetAssign(lv, op_, rv); cur->set_line(*this); return cur; diff --git a/ivl.def b/ivl.def index ebc1844fe..4e57899c5 100644 --- a/ivl.def +++ b/ivl.def @@ -272,6 +272,7 @@ ivl_stmt_lvals ivl_stmt_lwidth ivl_stmt_name ivl_stmt_nevent +ivl_stmt_opcode ivl_stmt_parm ivl_stmt_parm_count ivl_stmt_rval diff --git a/ivl_target.h b/ivl_target.h index 1c5db1177..3a1c39b70 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -1995,6 +1995,13 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net); * the statement.) The ivl_stmt_delay_expr function returns the * expression for the delay, or nil if there is no delay expression. * + * The blocking assignment (IVL_ST_ASSIGN) may have an associated + * opcode, that can be extracted from ivl_stmt_opcode(). This opcode + * is the compressed operator used it statements like this: + * foo += + * The ivl_stmt_opcode() returns null (0) if this is not a compressed + * assignment statment. + * * - IVL_ST_CASSIGN * This reflects a procedural continuous assignment to an l-value. The * l-value is the same as any other assignment (use ivl_stmt_lval). @@ -2088,6 +2095,8 @@ extern unsigned ivl_stmt_lvals(ivl_statement_t net); extern unsigned ivl_stmt_lwidth(ivl_statement_t net); /* IVL_ST_STASK */ extern const char* ivl_stmt_name(ivl_statement_t net); + /* IVL_ST_ASSIGN */ +extern char ivl_stmt_opcode(ivl_statement_t net); /* IVL_ST_STASK */ extern ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx); /* IVL_ST_STASK */ diff --git a/net_assign.cc b/net_assign.cc index f12bf64b2..286f4cd30 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -233,7 +233,12 @@ const NetExpr* NetAssignBase::get_delay() const } NetAssign::NetAssign(NetAssign_*lv, NetExpr*rv) -: NetAssignBase(lv, rv) +: NetAssignBase(lv, rv), op_(0) +{ +} + +NetAssign::NetAssign(NetAssign_*lv, char op, NetExpr*rv) +: NetAssignBase(lv, rv), op_(op) { } diff --git a/netlist.h b/netlist.h index cc000ecd4..8304bb777 100644 --- a/netlist.h +++ b/netlist.h @@ -2406,15 +2406,19 @@ class NetAssign : public NetAssignBase { public: explicit NetAssign(NetAssign_*lv, NetExpr*rv); + explicit NetAssign(NetAssign_*lv, char op, NetExpr*rv); ~NetAssign(); bool is_asynchronous(); + inline char assign_operator(void) const { return op_; } + virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; private: + char op_; }; class NetAssignNB : public NetAssignBase { diff --git a/t-dll-api.cc b/t-dll-api.cc index d6d1f08a0..b45da977e 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -2547,6 +2547,17 @@ extern "C" const char* ivl_stmt_name(ivl_statement_t net) return 0; } +extern "C" char ivl_stmt_opcode(ivl_statement_t net) +{ + switch (net->type_) { + case IVL_ST_ASSIGN: + return net->u_.assign_.oper; + default: + assert(0); + } + return 0; +} + extern "C" ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx) { switch (net->type_) { diff --git a/t-dll-proc.cc b/t-dll-proc.cc index 783ce6618..fbc55464e 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -210,6 +210,7 @@ bool dll_target::proc_assign(const NetAssign*net) /* Make the lval fields. */ make_assign_lvals_(net); + stmt_cur_->u_.assign_.oper = net->assign_operator(); assert(expr_ == 0); net->rval()->expr_scan(this); stmt_cur_->u_.assign_.rval_ = expr_; diff --git a/t-dll.h b/t-dll.h index 72ba60b22..62f2df303 100644 --- a/t-dll.h +++ b/t-dll.h @@ -729,6 +729,7 @@ struct ivl_statement_s { IVL_ST_CASSIGN, IVL_ST_DEASSIGN */ unsigned lvals_; struct ivl_lval_s*lval_; + char oper; // Operator if this is a compressed assignment. ivl_expr_t rval_; ivl_expr_t delay; // The following are only for NB event control. diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 652ea6a3f..401b049e7 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -179,6 +179,7 @@ void show_stmt_wait(ivl_statement_t net, unsigned ind) void show_statement(ivl_statement_t net, unsigned ind) { unsigned idx; + char opcode = 0; const ivl_statement_type_t code = ivl_statement_type(net); switch (code) { @@ -188,8 +189,11 @@ void show_statement(ivl_statement_t net, unsigned ind) break; case IVL_ST_ASSIGN: - fprintf(out, "%*sASSIGN \n", ind, "", - ivl_stmt_lwidth(net)); + opcode = ivl_stmt_opcode(net); + if (opcode == 0) + opcode = ' '; + fprintf(out, "%*sASSIGN opcode=%c\n", ind, "", + ivl_stmt_lwidth(net), opcode); for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1) show_assign_lval(ivl_stmt_lval(net, idx), ind+4); diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index a975ca729..776401876 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -565,6 +565,7 @@ static int show_stmt_alloc(ivl_statement_t net) static int show_stmt_assign_vector(ivl_statement_t net) { ivl_expr_t rval = ivl_stmt_rval(net); + struct vector_info res; /* Handle the special case that the expression is a real value. Evaluate the real expression, then convert the @@ -576,12 +577,10 @@ static int show_stmt_assign_vector(ivl_statement_t net) assignment. */ unsigned wid = ivl_stmt_lwidth(net); - struct vector_info vec; + res.base = allocate_vector(wid); + res.wid = wid; - vec.base = allocate_vector(wid); - vec.wid = wid; - - if (vec.base == 0) { + if (res.base == 0) { fprintf(stderr, "%s:%u: vvp.tgt error: " "Unable to allocate %u thread bits for " "r-value expression.\n", ivl_expr_file(rval), @@ -590,22 +589,20 @@ static int show_stmt_assign_vector(ivl_statement_t net) } fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", - vec.base, word, vec.wid); + res.base, word, res.wid); clr_word(word); - set_vec_to_lval(net, vec); - - clr_vector(vec); - return 0; + } else { + res = draw_eval_expr(rval, 0); } + if (ivl_stmt_opcode(net) != 0) + fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net)); - { struct vector_info res = draw_eval_expr(rval, 0); - set_vec_to_lval(net, res); - if (res.base > 3) - clr_vector(res); - } + set_vec_to_lval(net, res); + if (res.base > 3) + clr_vector(res); return 0;